Go+QML开发的跨平台桌面直播助手[上]
B站直播协议分析
上篇介绍协议分析,下篇介绍开发思路。
项目缘由
假期在家,群里有几个朋友决定尝个新鲜开直播娱乐一下,后来发现B站官方提供的直播姬只有弹幕显示功能,并没有点歌等其他自定义功能,网上的项目也比较少,而且一些点歌机不维护了导致功能有缺陷,因此打算开发一个自定义的具有多功能的直播助手,初步包含弹幕礼物显示,点歌等功能。
开发的思路是分析传输二进制包,从中找出我们想要的数据,以我们想要的方式显示出来。
总体过程
随便打开一个直播间,按 F12,切换到 Network 的 WS 栏。可以看到它是首先连接弹幕服务器,并且通过观察发现这个地址并不是固定的(应该是负载均衡的结果)。
然后发送一个握手包,携带了 Roomid,访问者 id,客户端版本等信息,最后还有一个 key,后来观察发现是通过请求某个接口获取的这个 key 值(就是 token)。
重点就是分析协议包。不管是接收还是发送的二进制包都有一个固定大小 16 字节的首部。这个首部的组成我用一个表格来表示:
偏移 | 长度 | 内容 |
---|---|---|
0 | 4 | 包的大小 |
4 | 4 | 未知(目前和分析无关) |
8 | 4 | 包类型 |
12 | 4 | 未知(目前和分析无关) |
除了首部之外的就是携带的数据部分了。在这里需要注意的一点是,由于瞬时信息量可能会很大,会把若干个包压缩为一个包发送,这个包组成是《包首部-包主体-下一个包首部-下一个包主体-…..等等》,而且因为包类型为 5 的数量最多,传输信息量会很大,所以是用 gzip 压缩了的,这里要注意。这里随手拿一个包举例:
...G............{"cmd":"DANMU_MSG","info":[[0,1,25,8322816,1584073975908,1584073720,0,"7905c3d4",0,0,0],"(=・ω・=)",[14006391,"桥本环零",0,1,0,10000,1,""],[17,"小糕兔","娜可糕糕",294526,16752445,"",0],[47,0,16746162,10074],["title-179-1","title-179-1"],0,0,null,{"ts":1584073975,"ct":"B0A7DFE4"},0,0,null,null,0]}...h............{"cmd":"DANMU_MSG","info":[[0,1,25,16777215,1584073975938,1584073264,0,"21635747",0,0,0],"包砸是我关注的up里唯一一个很可爱的",[339865528,"兰博基尼鬼怪",0,0,0,10000,1,""],[3,"包崽铺","喝薄荷奶绿",1506599,6406234,"",0],[10,0,9868950,"\u003e50000"],["",""],0,0,null,{"ts":1584073975,"ct":"657DC663"},0,0,null,null,0]}
可以看到这里就是瞬时有两条弹幕,变为了一个包。每个包都有自己的头部,可以自行格式化一下。
也不是所有类型为 5 的包都被压缩,只有某些可能数据量很大才会被压缩,比如 DANMU_MSG,SEND_GIFT 等,并且类型为 5 的可能是用户弹幕,礼物,贵宾进场,房间关注变动等,就是依靠 “cmd” 这个字段值来判别的,目前我已知的 cmd 有这么几种,可以根据需求来利用:
cmd | 内容 |
---|---|
DANMU_MSG | 用户弹幕 |
WELCOME | Vip,Svip进场(标注1) |
WELCOME_GUARD | 房管进场 |
ENTRY_EFFECT | 提督,总督等头衔 |
SEND_GIFT | 用户礼物 |
COMBO_SEND | 礼物连击 |
COMBO_END | 连击结束(标注2) |
ROOMD_RANK | 这个不太清楚是什么 |
NOTICE_MSG | 所有直播间的通告消息 |
标注 1: 我不太了解 B 站 Vip 的等级划分,我仅知道提督,总督等,还有老爷这些,其他不知道了,老爷是被划分到这一栏的。
标注 2: 如果送礼物连击是会有和《SEND_GIFT》不一样的特效的,连击结束也有提示,所以分开了。
这里给出一些用到的接口,后续可能会更新失效,F12 打开找即可,截止博客发出时均有效。
URL | 参数 | 说明 |
---|---|---|
http://api.live.bilibili.com/room/v1/Room/room_init | id | 查询房间短id,长id等信息 |
https://api.live.bilibili.com/room/v1/Danmu/getConf | room_id=xxx&platform=pc&player=web | 查询可用弹幕服务器列表,握手包的key |
https://api.bilibili.com/x/space/acc/info | mid=382297465&jsonp=jsonp | 根据userid查询用户个人信息 |
https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom | room_id=xxx | 查询房间信息,标题等 |
到这里其实就已经结束了,我们可以模拟连接某个弹幕服务器,然后按照要求发送握手包,随后一直接收信息,根据首部的类型 ID 可以判定不同的包,然后根据 cmd 字段判定消息类型,获取我们想要的字段值就可以了。再结合其他的一些接口就可以完整的获取直播间的各种信息了。
分析完后,就可以根据流程去写程序了,下一节介绍如何使用 Go 语言开发助手的后端部分。