使用 PHP 实现的 B 站直播间弹幕和礼物爬虫、弹幕分析与精彩时刻自动剪辑。
前言
起因
去年在 B 站发现一个后期超强的 UP 主:修仙不倒大小眼,专出 PDD 这样知名主播的吃鸡精彩集锦,涨粉超快。于是想怎么做这样的 UP,遇到的第一个问题便是素材,精彩时刻需要手动从直播录播中剪辑,很低效。
用户习惯
我经常看直播,但是很少发弹幕和送礼物,只有在主播玩出很溜的操作或讲很好玩的事情时,才会发弹幕互动、送礼物支持,经常看直播的室友也是如此。
基于这个用户习惯,不难推断出在直播间的弹幕高峰或礼物高峰期,主播应该做了些好玩的事情,比如吃到鸡了,或者全队被歼灭之类的…这些时刻都可以作为精彩时刻的素材。能写程序自动截取这些素材吗?答案是肯定的。
实现效果
弹幕抓取
数据统计
根据弹幕和礼物高峰生成的精彩剪辑
实现思路
通过爬虫抓取 B 站直播间数据,找出弹幕激增的时间点,使用 FFmpeg 自动剪辑时间点前后的视频即可。
本文代码:GitHub
1 | bilibili-live-crawler $ tree -L 2 |
准备 API
以 B 站欠王痒局长为例,进入他的 528 直播间,打开 Chrome 的开发者工具,看 Network 容易找出这些 API:
直播间原始信息
热门主播会有 2 个房间号:易识记的短房间号、原始长房间号,获取主播原始直播间信息的 API:
1 | Resquest: https://api.live.bilibili.com/room/v1/Room/room_init?id=528 |
弹幕服务器信息
直播间在加载时,会请求弹幕服务器的地址,即是我们要去爬取数据的服务器:
1 | Request: https://api.live.bilibili.com/api/player?id=cid:5441 // 5441 即原始房间号 |
直播推流信息
直播间会有 3~4 个视频推流地址,选用第一个主路线会更稳定:
1 | Request: https://api.live.bilibili.com/room/v1/Room/playUrl?cid=5441 |
协议分析
B 站和斗鱼一样,为传输直播数据自己设计了协议头部。需使用 Wireshark 抓包分析协议的细节,才能将爬虫的请求伪装成浏览器的请求,连接弹幕服务器去爬取直播间的数据。
找出弹幕服务器的 IP 地址:211.159.194.115
查看请求弹幕服务器的数据包:ip.addr == 211.159.194.115
前边三个包是我(10.0.1.34)与弹幕服务器(211.159.194.115)三次握手建立 TCP 连接的包。
请求的打包和解码,我参考 2016.3 的博客:B站直播弹幕协议详解,现在抓到的包协议头与博客中的不一样,B站重新修改过了,不过应该是为了兼容,这种旧协议头还能用。
请求协议头
下边这个是打开进入直播间时,客户端请求弹幕服务器的请求协议头,响应协议头类似:
1 | 00000000 00 00 00 35 00 10 00 01 00 00 00 07 00 00 00 01 ...5.... ........ |
进入直播间,打包生成连接服务器的协议头:
1 | // $roomID 是直播间的长房间号 |
响应数据
服务返回的 JSON 数据包的协议头如下:
1 | 00000835 7b 22 69 6e 66 6f 22 3a 5b 5b 30 2c 31 2c 32 35 {"info": [[0,1,25 |
解码响应的数据体:
1 | function decodeMessage($socket) { |
心跳包
如果客户端出现突然断网等异常情况,服务端依旧会继续推送数据,维护这种半打开的 TCP 连接将会浪费服务器的资源。客户端可以每隔一小段时间给服务端发送心跳包来保活,如果服务端一定超时时间内没收到某个客户端的心跳包,就主动断开连接。
B 站的弹幕服务器也有类似的机制,随便打开一个未开播的直播间,抓包将看到每隔 30s 左右会给服务端发送一个心跳包,协议头第四部分的值从 7 修改为 2 即可。如果不发送心跳包,弹幕服务器将在 1~2min 内主动断开连接。
1 | // 发送心跳包 |
录播并剪辑精彩时刻
录播:直接使用 FFmpeg 保存推流地址的视频即可
剪辑:根据 每分钟 的弹幕数量变化情况,如果出现峰值,取峰值 前后的一分钟 作为精彩部分。
峰值的判断标准:
- 对痒局长这样的大主播:直播间人很多,玩出甩狙瞬狙这种骚操作弹幕会激增很多,比如是前一分钟的**三倍**
- 对小主播:人一般比较少,弹幕数量波动不大,出现精彩操作时也涨幅也不大
以上加下划线的判定粒度、判定标准都可根据自己喜欢的主播修改,具体参考 edit.php 的实现。还可以为精彩时刻加上弹幕判定,比如分析是否有大量的 666、233、基本操作、学不来之类的词集中出现等等。
弹幕分析
参考 结巴分词 的算法,可用于生成直播的词图、分析粉丝的习惯用语等等。我参考的教程:
总结
开发遇到了两个难点
- 协议头部:参考的博客里边逆向 B 站官方 C# 版客户端代码,分析协议组成,感谢博主 lyyyuna
- 分词算法:参考的是结巴分词的前缀词典与动态规划算法,算法能力待提升 :(
再看看人家斗鱼,有开放使用的 《斗鱼弹幕服务器第三方接入协议》,协议也不会修改,兴趣使然写了 B 站的爬虫,这种根据弹幕峰值剪辑视频的想法应用在斗鱼上,估计会更有价值 :)