如今,市面上已经有不少开源项目可以用于连接 B 站直播 WebSocket 获取信息流。
但在实际使用中,常常发现它们并不能完全满足个性化需求。
为了更好地适配自己的业务场景,我决定自己动手实现一套连接方案。
因此,我整理了整个实现过程的一些关键步骤和注意事项,希望能够对有相似需求的朋友们有所帮助
PHP可以直接通过 composer 安装相关库来直接链接B站直播间并对数据进行解密,点击前往GitHub
也有现成的 B站机器人弹幕监控,支持礼物答谢、定时广告、关注感谢,自动回复等,内置积分商城,可通过 docker 快速部署,点击前往GitHub
接入前准备
获取直播间真实ID
网页版 直播间URL 携带的房间号可能是短号,并不保证一定为真实地址,因此建议调用该接口以确保房间号无误
请求方式:GET
参数名 | 类型 | 内容 |
---|---|---|
room_id | int | 直播间 ID |
请求响应示例与字段说明
curl -G 'https://api.live.bilibili.com/room/v1/Room/get_info' \
--data-urlencode 'room_id=27668995'
{
"code": 0,
"msg": "ok",
"message": "ok",
"data": {
"uid": 3493124609411229, // 主播id
"room_id": 27668995, // 真实房间id
"short_id": 0, // 直播间短号,0为无短号
"attention": 13353, // 关注数量
"online": 4173, // 观看人数
"is_portrait": false, // 是否是竖屏
"description": "一只屑狐狸,不专业的CV,新晋歌杂,不缺席你的每一天...直播时间: 晚22:00-02:00,下午3:00-7:00闪现打游戏", // 描述
"live_status": 1, // 直播间状态:0-未开播,1-直播中,2-轮播中
"area_id": 371, // 分区id
"parent_area_id": 9, // 父分区id
"parent_area_name": "虚拟主播", // 父分区名称
"old_area_id": 6, // 旧版分区id
"background": "", // 背景图片链接
"title": "不给糖就捣蛋", // 标题
"user_cover": "https://i0.hdslb.com/bfs/live/new_room_cover/22426f0ead9804fabd06ad1c4305e2641a4e6d11.jpg", // 封面
"keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe11011431000027668995752wsi.jpg", // 关键帧
"is_strict_room": false, // 待观测
"live_time": "2024-11-01 14:25:09", // 开播时间
"tags": "御姐,屑狐狸,狐仙,憨憨,温柔", // 标签
"is_anchor": 0, // 待观测
"room_silent_type": "", // 禁言状态
"room_silent_level": 0, // 禁言等级
"room_silent_second": 0, // 禁言等级(单位秒)
"area_name": "虚拟日常", // 分区名称
"pendants": "", // 待观测
"area_pendants": "", // 待观测
"hot_words": [
"2333333",
"喂,妖妖零吗",
"红红火火恍恍惚惚",
"FFFFFFFFFF",
"Yooooooo",
"啪啪啪啪啪",
"666666666",
"老司机带带我",
"你为什么这么熟练啊",
"gg",
"prprpr",
"向大佬低头",
"请大家注意弹幕礼仪哦!",
"还有这种操作!",
"囍",
"打call",
"你气不气?",
"队友呢?"
], // 热词
"hot_words_status": 0, // 热词状态
"verify": "", // 待观测
"new_pendants": { // 头像框
"frame": { // 头像框信息
"name": "大乱斗乱斗之王", // 名称
"value": "https://i0.hdslb.com/bfs/live/fc28a2a4123154012e0ce3da1273de5f17e81b24.png", // 头像框图片URL
"position": 0, // 位置
"desc": "", // 描述
"area": 0, // 分区
"area_old": 0, // 旧分区
"bg_color": "", // 背景色
"bg_pic": "", // 背景图
"use_old_area": false // 是否旧分区号
},
"badge": { // 大V才会有的信息
"name": "v_person", // 认证类型:v_person=个人认证(黄),v_company=企业认证(蓝)
"position": 3, // 位置,可能是个枚举
"value": "", // 待观测
"desc": "bilibili 知名UP主、直播高能主播" // 描述
},
"mobile_frame": { // 头像框信息,手机版,可能为null
"name": "大乱斗乱斗之王", // 名称
"value": "https://i0.hdslb.com/bfs/live/fc28a2a4123154012e0ce3da1273de5f17e81b24.png", // 头像框图片URL
"position": 0, // 位置
"desc": "", // 描述
"area": 0, // 分区
"area_old": 0, // 旧分区
"bg_color": "", // 背景色
"bg_pic": "", // 背景图
"use_old_area": false // 是否旧分区号
},
"mobile_badge": { // 大V才会有的信息,手机版,可能为null
"name": "v_person", // 认证类型:v_person=个人认证(黄),v_company=企业认证(蓝)
"position": 3, // 位置,可能是个枚举
"value": "", // 待观测
"desc": "bilibili 知名UP主、直播高能主播" // 描述
}
},
"up_session": "557568462506308099", // 待观测
"pk_status": 0, // pk状态
"pk_id": 0, // pk id
"battle_id": 0, // 待观测
"allow_change_area_time": 0, // 待观测
"allow_upload_cover_time": 0, // 待观测
"studio_info": { // 待观测
"status": 0, // 待观测
"master_list": [
]
}
}
}
获取信息流认证秘钥
该接口可以获取到对应直播间信息流的链接地址,以及建立链接需要认证的token信息
注意: B 站更新了隐私政策, 连接建立 5 分钟左右, 若该连接认证时传入信息来自未登录用户, 会提示 为保护用户隐私,未注册登陆用户将无法查看他人昵称, 随后所有发送弹幕的用户 id 都为 0, 用户名部分也使用 * 保护,因此调用本接口时需要传递 cookie
注意: ws 与 wss 连接地址带有路径 /sub, 如 wss://tx-sh-live-comet-08.chat.bilibili.com:443/sub
请求方式:GET
请求地址:https://api.live.bilibili.com/xlive/web-room/v1/index/getDanm...
参数名 | 类型 | 内容 |
---|---|---|
id | int | 直播间真实id |
请求响应示例与字段说明
curl -G 'https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo' \
--data-urlencode 'id=30118851'
{
"code":0, // 0:成功,65530:token错误(登录错误),1:错误,60009:分区不存在,其他错误仍需观察
"message":"0", // 错误信息
"ttl":1, // 默认为1
"data":{ // 信息本体
"group":"live", // 不重要,默认live
"business_id":0, // 不重要,默认 0
"refresh_row_factor":0.125, // 不重要,默认0.125
"refresh_rate":100, // 不重要,默认100
"max_delay":5000, // 不重要,默认5000
"token":"TrF6FaSlmxVBM4eBYGoaWPuZ-xVL-bhK80waLbGRfpj6JiLkjgaxLcu5whFM6iEBrQFw8wJwdraBJwkctMzMrkyP7kmWkRAmFUa_Z1aiXVDhyMwsiQe81KHMGC82tuyWF9iHNstIX-M0IhU=", // 认证密钥
"host_list":[ // 信息流服务器节点列表
{
"host":"tx-sh-live-comet-08.chat.bilibili.com", // 服务器域名
"port":2243, // tcp端口
"wss_port":443, // wss 端口
"ws_port":2244 // ws端口
},
{
"host":"tx-bj-live-comet-08.chat.bilibili.com",
"port":2243,
"wss_port":443,
"ws_port":2244
},
{
"host":"broadcastlv.chat.bilibili.com",
"port":2243,
"wss_port":443,
"ws_port":2244
}
]
}
}
信息流接入
数据包为MQ(Message Queue,消息队列)使用 Websocket 或 TCP 连接作为通道,具体格式为 弹幕协议 + 正文数据
操作流程:
连接信息流服务器节点 -> 发送认证包 -> 接收认证包回应 -> 接收普通包&(每30秒发送心跳包 -> 接收心跳回应)
协议格式:基于websocket之上的应用层协议,所有字段 大端 对齐
- Packet Length:整个Packet的长度,包含Header
- Header Length:Header的长度,固定为16
- Version:协议版本
- Operation:操作码
- Sequence ID:保留字段,可以忽略
- Body:消息体,客户端解析Body之前请先解析Version字段
Version 说明:
0 - 普通包正文不使用压缩
1 - 心跳及认证包正文不使用压缩
2 - 普通包(zlib压缩)
3 - 普通包(brotli压缩)Operation 说明:
2 - 客户端发送的心跳包(30秒发送一次)
3 - 服务器收到心跳包的回复
5 - 服务器推送的弹幕消息包
7 - 客户端发送的鉴权包(客户端发送的第一个包)
8 - 服务器收到鉴权包后的回复注意:B站最近加强了风控,建议在建立连接时携带好用户的cookie以避免风控限流
认证包构建
注意: 认证包需要在握手成功 5 秒内发送, 否则强制断开连接
认证包头部信息基于上述协议格式不再赘述,仅说明 Body 如何构建
字段 | 类型 | 说明 |
---|---|---|
uid | int | 用户uid |
roomid | int | 主播房间id |
protover | int | 协议版本,决定了后续数据包的 Version |
buvid | string | 用户buvid3,可在cookie中获得 |
platform | string | 平台,传web即可 |
type | int | 不确定用途,目前B站网页版传2,照着传即可 |
key | string | 获取信息流认证秘钥接口提供的token |
protover 说明:
2 - 后续正文以 zlib 方式返回
3 - 后续正文以 brotli 方式返回
示例:
00000000: 0000 0152 0010 0001 0000 0007 0000 0001 ...R............
00000001: 7b22 7569 6422 3a34 3332 3530 3531 2c22 {"uid":4325051,"
00000002: 726f 6f6d 6964 223a 3331 3432 3735 3432 roomid":31427542
00000003: 2c22 7072 6f74 6f76 6572 223a 332c 2262 ,"protover":3,"b
00000004: 7576 6964 223a 2232 4445 3846 4141 312d uvid":"2DE8FAA1-
00000005: 3642 4643 2d45 3741 412d 3031 3041 2d31 6BFC-E7AA-010A-1
00000006: 3039 4544 3039 3443 4245 3537 3935 3139 09ED094CBE579519
00000007: 696e 666f 6322 2c22 706c 6174 666f 726d infoc","platform
00000008: 223a 2277 6562 222c 2274 7970 6522 3a32 ":"web","type":2
00000009: 2c22 6b65 7922 3a22 375f 6573 4f70 564e ,"key":"7_esOpVN
0000000a: 697a 5570 4732 7069 3169 7741 2d79 3651 izUpG2pi1iwA-y6Q
0000000b: 4545 4550 734a 7872 666a 6c4c 5f73 4e50 EEEPsJxrfjlL_sNP
0000000c: 6b77 4f55 385a 7255 4150 334a 7951 746e kwOU8ZrUAP3JyQtn
0000000d: 4154 6748 474c 645f 514a 616b 794b 4d54 ATgHGLd_QJakyKMT
0000000e: 4b75 717a 3856 5174 6474 5479 5f75 476c Kuqz8VQtdtTy_uGl
0000000f: 5541 3958 6d75 334f 507a 6944 5170 3952 UA9Xmu3OPziDQp9R
00000010: 5832 6f57 4366 5356 3345 7778 3554 4532 X2oWCfSV3Ewx5TE2
00000011: 6c6a 4552 616e 684f 3757 7230 695f 3641 ljERanhO7Wr0i_6A
00000012: 584f 3862 6d38 634f 5757 5649 4a31 7966 XO8bm8cOWWVIJ1yf
00000013: 5535 4c63 7638 484b 3864 564e 4954 6e74 U5Lcv8HK8dVNITnt
00000014: 7144 4669 7339 5471 586d 544f 344e 413d qDFis9TqXmTO4NA=
00000015: 227d "}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。