如今,市面上已经有不少开源项目可以用于连接 B 站直播 WebSocket 获取信息流。
但在实际使用中,常常发现它们并不能完全满足个性化需求。
为了更好地适配自己的业务场景,我决定自己动手实现一套连接方案。
因此,我整理了整个实现过程的一些关键步骤和注意事项,希望能够对有相似需求的朋友们有所帮助
PHP可以直接通过 composer 安装相关库来直接链接B站直播间并对数据进行解密,点击前往GitHub
也有现成的 B站机器人弹幕监控,支持礼物答谢、定时广告、关注感谢,自动回复等,内置积分商城,可通过 docker 快速部署,点击前往GitHub
接入前准备
获取直播间真实ID
网页版 直播间URL 携带的房间号可能是短号,并不保证一定为真实地址,因此建议调用该接口以确保房间号无误
请求方式:GET
参数名 | 类型 | 内容 |
---|---|---|
room_id | int | 直播间 ID |
请求响应示例与字段说明
展开查看
bash curl -G 'https://api.live.bilibili.com/room/v1/Room/get_info' \ --data-urlencode 'room_id=27668995'
json { "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/getDanmuInfo
参数名 | 类型 | 内容 |
---|---|---|
id | int | 直播间真实id |
请求响应示例与字段说明
展开查看
bash curl -G 'https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo' \ --data-urlencode 'id=30118851'
json { "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 "}