Bilibili
直播间弹幕处理库
golang
的b站信息流处理 支持近百种消息命令类型 高性能 低占用的信息流处理库,包含弹幕/礼物/大航海/SC等一切你想要的数据
介绍
go-bili-chat
是一个用于处理 Bilibili 直播间信息流库,可以用于开发自己的 Bilibili 直播间信息流处理程序。
b站直播间信息流以Websocket传输并加密, 含有几十个不同的命令, 本项目对其进行了解析, 并提供了一些简单的处理方法, 以便于开发者快速开发自己的程序。
快速使用
信息流处理流程为: 客户端收到信息 -> 解析后由处理器进行分发
因此, 你需要先将命令处理函数绑定到处理器, 再开启直播间进行处理,
1. 一个简单的使用示例:
package main
import (
"fmt"
bili "github.com/FishZe/go-bili-chat"
handle "github.com/FishZe/go-bili-chat/handler"
)
func main() {
// 新建一个命令处理器
h := bili.GetNewHandler()
// 注册一个处理,将该直播间的弹幕消息绑定到这个函数
h.AddOption(handle.CmdDanmuMsg, 26097368, func(event handle.MsgEvent) {
// 打印出弹幕消息
fmt.Printf("[%v] %v: %v\n", event.RoomId, event.DanMuMsg.Data.Sender.Name, event.DanMuMsg.Data.Content)
})
// 连接到直播间
_ = h.AddRoom(26097368)
// 启动处理器
h.Run()
}
特殊地, 绑定函数的直播间号为0时,绑定所有房间
2. 也可以先运行命令处理器,再添加房间:
package main
import (
"fmt"
bili "github.com/FishZe/go-bili-chat"
handle "github.com/FishZe/go-bili-chat/handler"
"time"
)
func main() {
h := bili.GetNewHandler()
// 运行处理器
go h.Run()
h.AddOption(handle.CmdDanmuMsg, 26097368, func(event handle.MsgEvent) {
fmt.Printf("[%v] %v: %v\n", event.RoomId, event.DanMuMsg.Data.Sender.Name, event.DanMuMsg.Data.Content)
})
_ = h.AddRoom(26097368)
for {
time.Sleep(time.Second)
}
}
3. 当然了,也可以删除房间:
package main
import (
"fmt"
bili "github.com/FishZe/go-bili-chat"
handle "github.com/FishZe/go-bili-chat/handler"
)
func main() {
h := bili.GetNewHandler()
h.AddOption(handle.CmdDanmuMsg, 26097368, func(event handle.MsgEvent) {
fmt.Printf("[%v] %v: %v\n", event.RoomId, event.DanMuMsg.Data.Sender.Name, event.DanMuMsg.Data.Content)
})
_ = h.AddRoom(26097368)
_ = h.DelRoom(26097368)
h.Run()
}
4. 还可以删除处理函数
package main
import (
"fmt"
bili "github.com/FishZe/go-bili-chat"
handle "github.com/FishZe/go-bili-chat/handler"
)
func main() {
h := bili.GetNewHandler()
danmu := h.AddOption(handle.CmdDanmuMsg, 26097368, func(event handle.MsgEvent) {
fmt.Printf("[%v] %v: %v\n", event.RoomId, event.DanMuMsg.Data.Sender.Name, event.DanMuMsg.Data.Content)
})
_ = h.AddRoom(26097368)
h.DelOption(danmu)
h.Run()
}
5. 对于连接房间过多的情况, 建议先go h.Run()
再添加房间, 否则会阻塞通道造成内存大量占用
go h.Run()
_ = h.AddRoom(26097368)
_ = h.AddRoom(26097369)
_ = h.AddRoom(26097370)
// sth...
关于为什么在处理绑定函数时, 多一个直播间号的参数, 因为考虑到可能会有根据不同的直播间分发处理消息的需求
6. 也可以获得当前的连接房间个数
sum := h.CountRoom()
fmt.Println("当前连接房间数: ", sum)
7. 对于接入的服务器: 程序提供了3个模式:
DefaultPriority: 默认模式, 按照b站提供的顺序进行连接
DelayPriority: 低延迟模式, 将会在连接前计算到所有提供的服务器的延迟, 并选择最低的(连接会慢一些)
NoCDNPriority: 不使用CDN模式, 适合大量连接的情况
默认使用的模式为DefaultPriority
, 有需要的可以使用这种方式修改:
bili.SetClientPriorityMode(bili.DelayPriority)
8. 默认使用的Json解析器为sonic
, 有需要自定义json
解析器的可以使用这种方式:
type Json struct{}
func (j *Json) Unmarshal(data []byte, v interface{}) error {
return json.Unmarshal(data, v)
}
func (j *Json) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v)
}
bili.SetJsonCoder(&Json{})
具体的示例代码可以查看example/main.gp
9. 对于需要查看DEBUG
日志的情况, 可以修改日志等级
bili.ChangeLogLevel(log.DebugLevel)
开启DEBUG
日志后, 可以看到所有的数据包和分发过程, 如果想要直观的看到分发到的函数名称, 可以在AddOption
中写明该函数的备注名
h.AddOption(handle.CmdDanmuMsg, 21545805, func(event handle.MsgEvent) {
fmt.Printf("[%v][弹幕] %v (%v): %v\n", event.RoomId, event.DanMuMsg.Data.Sender.Name, event.DanMuMsg.Data.Medal.MedalName, event.DanMuMsg.Data.Content)
}, "弹幕处理")
控制台会显示类似如下的日志
[bili-live][02-21 16:42:55][DEBUG]: distribute DANMU_MSG cmd to 弹幕处理
所有支持的消息类型:
这些常量请填入go-bili-chat.GetNewHandler().AddOption()
的第一个参数
变量名 |
命令类型 |
含义 |
CmdDanmuMsg |
"DANMU_MSG" |
弹幕消息 |
CmdLikeInfoV3Click |
"LIKE_INFO_V3_CLICK" |
直播间点赞信息 |
CmdSuperChatEntrance |
"SUPER_CHAT_ENTRANCE" |
超级留言入口样式 |
CmdSuperChatMessage |
"SUPER_CHAT_MESSAGE" |
醒目留言消息 |
CmdSuperChatMessageDelete |
"SUPER_CHAT_MESSAGE_DELETE" |
醒目留言被删除 |
CmdWatchedChange |
"WATCHED_CHANGE" |
直播间看过人数改变 |
CmdSendGift |
"SEND_GIFT" |
赠送礼物 |
CmdComboSend |
"COMBO_SEND" |
礼物连击 |
CmdSpecialGift |
"SPECIAL_GIFT" |
特殊礼物 |
CmdOnlineRankCount |
"ONLINE_RANK_COUNT" |
高能榜观众数量 |
CmdOnlineRankV2 |
"ONLINE_RANK_V2" |
高能榜刷新 |
CmdOnlineRankTop3 |
"ONLINE_RANK_TOP3" |
高能用户前三名 |
CmdInteractWord |
"INTERACT_WORD" |
进场或关注消息 |
CmdStopLiveRoomList |
"STOP_LIVE_ROOM_LIST" |
停止直播的房间列表 |
CmdLikeInfoV3Update |
"LIKE_INFO_V3_UPDATE" |
直播间点赞数更新 |
CmdHotRankChange |
"HOT_RANK_CHANGED" |
分区排名变化 |
CmdHotRankChangedV2 |
"HOT_RANK_CHANGED_V2" |
二级分区排名变化 |
CmdAreaRankChanged |
"AREA_RANK_CHANGED" |
直播间所在分区的排名改变 |
CmdNoticeMsg |
"NOTICE_MSG" |
通知消息 |
CmdRoomRealTimeMessageUpdate |
"ROOM_REAL_TIME_MESSAGE_UPDATE" |
直播间相关信息更新 |
CmdWidgetBanner |
"WIDGET_BANNER" |
网页端直播间标题下的横幅内容 |
CmdGuardHonorThousand |
"GUARD_HONOR_THOUSAND" |
千舰推送 |
CmdGuardAchievementRoom |
"GUARD_ACHIEVEMENT_ROOM" |
舰队规模达成成就 |
CmdPreparing |
"PREPARING" |
直播准备 |
CmdLive |
"LIVE" |
开始直播 |
CmdRoomChange |
"ROOM_CHANGE" |
直播间信息更改 |
CmdRoomBlockMsg |
"ROOM_BLOCK_MSG" |
禁言消息 |
CmdSysMsg |
"SYS_MSG" |
系统消息 |
CmdFullScreenSpecialEffect |
"FULL_SCREEN_SPECIAL_EFFECT" |
全屏特效 |
CmdCommonNoticeDanmaku |
"COMMON_NOTICE_DANMAKU" |
直播间所在分区排名提升祝福 |
CmdTradingScore |
"TRADING_SCORE" |
每日任务 |
CmdGuardBuy |
"GUARD_BUY" |
购买大航海 |
CmdGiftStarProcess |
"GIFT_STAR_PROCESS" |
礼物星球点亮 |
CmdWarning |
"WARNING" |
超管警告 |
CmdCutOff |
"CUT_OFF" |
被切断直播 |
CmdRoomAdminRevoke |
"ROOM_ADMIN_REVOKE" |
房管撤销 |
CmdRoomSilentOff |
"ROOM_SILENT_OFF" |
关闭直播间全部禁言 |
CmdRoomSilentOn |
"ROOM_SILENT_ON" |
开启直播间全部禁言 |
CmdRoomAdminEntrance |
"room_admin_entrance" |
修改房管的提示语 (只有涉及的用户会提示) |
CmdRoomAdmins |
"ROOM_ADMINS" |
房管列表更新 |
CmdRoomSkinMsg |
"ROOM_SKIN_MSG" |
[存疑] 房间皮肤 |
CmdChangeRoomInfo |
"CHANGE_ROOM_INFO" |
[存疑] 直播间背景更换 |
CmdEntryEffect |
"ENTRY_EFFECT" |
进场特效 |
CmdUserToastMsg |
"USER_TOAST_MSG" |
上舰提示消息 |
CmdOfficialRoomEvent |
"OFFICIAL_ROOM_EVENT" |
官方房间事件 |
CmdHeartBeatReply |
"HEARTBEAT_REPLY" |
[自定义] 心跳包回复 |
CmdPopularityRedPocketStart |
"POPULARITY_RED_POCKET_START" |
直播间发红包 |
CmdPopularityRedPocketNew |
"POPULARITY_RED_POCKET_NEW" |
[存疑] 发出红包 |
CmdPopularityRedPocketWinnerList |
"POPULARITY_RED_POCKET_WINNER_LIST" |
抢到红包的人的信息 |
CmdPkBattleProcess |
"PK_BATTLE_PROCESS" |
[存疑] PK相关 |
CmdPkBattleProcessNew |
"PK_BATTLE_PROCESS_NEW" |
[存疑] PK相关 |
CmdPkBattlePreNew |
"PK_BATTLE_PRE_NEW" |
[存疑] PK相关 |
CmdPkBattlePre |
"PK_BATTLE_PRE" |
[存疑] PK相关 |
CmdPkBattleFinalProcess |
"PK_BATTLE_FINAL_PROCESS" |
[存疑] PK相关 |
CmdPkBattleStart |
"PK_BATTLE_START" |
[存疑] PK相关 |
CmdPkBattleStartNew |
"PK_BATTLE_START_NEW" |
[存疑] PK相关 |
CmdPkBattlePunishEnd |
"PK_BATTLE_PUNISH_END" |
[存疑] PK相关 |
CmdPkBattleSettleV2 |
"PK_BATTLE_SETTLE_V2" |
[存疑] PK相关 |
CmdPkBattleSettle |
"PK_BATTLE_SETTLE" |
[存疑] PK相关 |
CmdPkBattleEnd |
"PK_BATTLE_END" |
[存疑] PK相关 |
CmdPkBattleSettleUser |
"PK_BATTLE_SETTLE_USER" |
[存疑] PK相关 |
CmdPkBattleRankChange |
"PK_BATTLE_RANK_CHANGE" |
[存疑] PK相关 |
CmdPkBattleSettleNew |
"PK_BATTLE_SETTLE_NEW" |
[存疑] PK相关 |
CmdPkBattleMatchTimeout |
"PK_BATTLE_MATCH_TIMEOUT" |
[存疑] PK相关 |
CmdPkBattleAbnormal |
"PK_BATTLE_ABNORMAL" |
[存疑] PK相关 |
CmdPkBattleEntrance |
"PK_BATTLE_ENTRANCE" |
[存疑] PK相关 |
CmdPkBattleVideoPunishBegin |
"PK_BATTLE_VIDEO_PUNISH_BEGIN" |
[存疑] PK相关 |
CmdPkBattleVideoPunishEnd |
"PK_BATTLE_VIDEO_PUNISH_END" |
[存疑] PK相关 |
CmdGotoBuyFlow |
"GOTO_BUY_FLOW" |
[存疑] 购物车提示消息 |
CmdShoppingExplainCard |
"SHOPPING_EXPLAIN_CARD" |
[存疑] 购物车相关 |
CmdShoppingCartShow |
"SHOPPING_CART_SHOW" |
[存疑] 购物车显示状态 |
CmdShoppingBubblesStyle |
"SHOPPING_BUBBLES_STYLE" |
[存疑] 购物车相关 |
CmdSelectedGoodsInfo |
"SELECTED_GOODS_INFO" |
[存疑] 购物车相关 |
CmdHotBuyNum |
"HOT_BUY_NUM" |
[存疑] 购物车相关 |
CmdVoiceJoinRoomCountInfo |
"VOICE_JOIN_ROOM_COUNT_INFO" |
[存疑] 语音连线相关 |
CmdVoiceJoinList |
"VOICE_JOIN_LIST" |
[存疑] 语音连线相关 |
CmdVoiceJoinStatus |
"VOICE_JOIN_STATUS" |
[存疑] 语音连线相关 |
CmdVoiceJoinSwitch |
"VOICE_JOIN_SWITCH" |
[存疑] 语音连线相关 |
CmdVideoConnectionJoinStart |
"VIDEO_CONNECTION_JOIN_START" |
[存疑] 视频连线相关 |
CmdVideoConnectionMsg |
"VIDEO_CONNECTION_MSG" |
视频连线提示语 |
CmdVideoConnectionJoinEnd |
"VIDEO_CONNECTION_JOIN_END" |
视频连线结束 |
CmdMultiVoiceOperating |
"MULTI_VOICE_OPERATING" |
[存疑] 视频连线相关 |
CmdMultiVoiceApplicationUser |
"MULTI_VOICE_APPLICATION_USER" |
申请视频连线 |
CmdAnchorLotCheckStatus |
"ANCHOR_LOT_CHECK_STATUS" |
[存疑] 天选相关 |
CmdAnchorLotEnd |
"ANCHOR_LOT_END" |
天选结束 |
CmdAnchorLotAward |
"ANCHOR_LOT_AWARD" |
天选结果 |
CmdInteractiveUser |
"INTERACTIVE_USER" |
[存疑] 预言玩法相关 |
CmdUserVirtualMvp |
"USER_VIRTUAL_MVP" |
[存疑] 守护圣法师相关 |
CmdWidgetWishList |
"WIDGET_WISH_LIST" |
[存疑] 许愿玩法相关 |
CmdPlayTogether |
"PLAY_TOGETHER" |
|
CmdPopularRankChanged |
"POPULAR_RANK_CHANGED" |
|
CmdDanMuAggregation |
"DANMU_AGGREGATION" |
|
CmdLiveInteractiveGame |
"LIVE_INTERACTIVE_GAME" |
|
CmdRecommendCard |
"RECOMMEND_CARD" |
|
CmdWidgetGiftStarProcess |
"WIDGET_GIFT_STAR_PROCESS" |
|
CmdAnchorLotStart |
"ANCHOR_LOT_START" |
|
CmdHotRoomNotify |
"HOT_ROOM_NOTIFY" |
|
CmdLiveOpenPlatformGame |
"LIVE_OPEN_PLATFORM_GAME" |
|
CmdLivePanelChangeContent |
"LIVE_PANEL_CHANGE_CONTENT" |
|
CmdGiftPanelPlan |
"GIFT_PANEL_PLAN" |
|
CmdRingStatusChange |
"RING_STATUS_CHANGE" |
|
CmdRingStatusChangeV2 |
"RING_STATUS_CHANGE_V2" |
|
CmdRoomLock |
"ROOM_LOCK" |
|
CmdLiveMultiViewChange |
"LIVE_MULTI_VIEW_CHANGE" |
|
CmdMvRoleChange |
"MV_ROLE_CHANGE" |
|
CmdMultiVoiceOperatin |
"MULTI_VOICE_OPERATING" |
|
CmdPanelInteractiveNotifyChange |
"PANEL_INTERACTIVE_NOTIFY_CHANGE" |
|
CmdCheckSingStatus |
"CHECK_SING_STATUS" |
|
CmdRoomModuleDisplay |
"ROOM_MODULE_DISPLAY" |
|
CmdVoiceChatUpdate |
"VOICE_CHAT_UPDATE" |
|
CmdReenterLiveRoom |
"REENTER_LIVE_ROOM" |
|
CmdActivityBannerChangeV2 |
"ACTIVITY_BANNER_CHANGE_V2" |
|
CmdActivityBannerChange |
"ACTIVITY_BANNER_CHANGE" |
|
CmdVideoConnectionStart |
"VIDEO_CONNECTION_START" |
|
CmdGuideInfoStatus |
"GUIDE_INFO_STATUS" |
|
CmdObsShieldStatusUpdate |
"OBS_SHIELD_STATUS_UPDATE" |
|
CmdAnchorNormalNotify |
"ANCHOR_NORMAL_NOTIFY" |
|
CmdBlinkStickerTitleRejected |
"BLINK_STICKER_TITLE_REJECTED" |
|
CmdDanmuTagChanged |
"DANMU_TAG_CHANGED" |
|
CmdHourRankAwards |
"HOUR_RANK_AWARDS" |
|
CmdLivePanelChange |
"LIVE_PANEL_CHANGE" |
|
CmdLiveRoomToastMessage |
"LIVE_ROOM_TOAST_MESSAGE" |
|
CmdLogInNotice |
"LOG_IN_NOTICE" |
|
CmdStudioRoomClose |
"STUDIO_ROOM_CLOSE" |
|
CmdWinActivity |
"WIN_ACTIVITY" |
|
由于我也不是很明白b站的命令, 所以这里只是列出了我知道的命令, 如果有人知道更多的命令, 请在issue中提出, 我会及时更新。
相信可以通过直译看懂这些命令...
消息处理函数
消息处理函数的原型为:
func someFunc(event MsgEvent)
其中MsgEvent
的定义为:
type MsgEvent struct {
//原始命令
Cmd string
//直播间号
RoomId int
// 以下为不同的消息类型
DanMuMsg *DanMuMsg
SuperChatMessage *SuperChatMessage
// 下同, 可参考上方的消息类型, 取消Cmd即为结构体名称...
...
}
消息结构体
这是弹幕消息的例子
type DanMuMsg struct {
Cmd string `json:"cmd"`
Data struct {
Sender struct {
Uid int64
Name string
RoomId int64
}
Medal FansMedal
Content string
SendTimeStamp int
SendMillionTimeStamp int64
SenderEnterRoomTimeStamp int
}
}
结构体内容, 请参考go-bili-chat/Handler/template.go
中的定义
因为30个实在是太多了, 所以我就不一一列出来了...
在弹幕消息中, 我还没有完全明白每个参数的含义, 强烈欢迎各位PR完善
性能
具体可以参考Issue #24
感谢@XiaoMiku01提供的压测:
上海腾讯云 4C8G 10M Linux
同时连接5.8w个直播中的房间,内存占用 4.5G 左右, CPU 213% (平均 42%)
抽象画
+============================+ +=================+
| LiveRoom 1 | | |
| goroutine heart beat | | → → goroutine your function
| goroutine receive msg → → ↓| | |
| goroutine msg handler ← ← ←| | → → goroutine your function
+================|↓|=========+ _ |
→ → → → → → → → goroutine → → goroutine your function
+============================+ _ |
| LiveRoom 1 | | msg distribute → → goroutine your function
| goroutine heart beat | | |
| goroutine receive msg → → ↓| | → → goroutine your function
| goroutine msg handler ← ← ←| | |
+================|↓|=========+ _ → → goroutine your function
→ → → → → → → → |
_ → → goroutine your function
+======|↑|========+
↑
↑
+=======|↑|========+
| |
| main goroutine |
| |
+==================+