KO
|
EN
gitlite — search
Search
#typescript
#ai-agents
#ai
#dsh-plugin
#deepseek-harness
#open-source
#cli
#claude-code
#codex
#developer-tools
#react
#windows
bili_danmu
★ 170
Open GitHub ↗
Bilibili 直播、弹幕录制回放工具 go1.26+
Download README (.md)
Explore Similar Repositories
Entitas-Sync-Framework
:
Networking framework for Entitas ECS. Targeted at turnbased games or other slow-paced genres.
Pylette
:
A Python library for extracting color palettes from supplied images.
csrf-protection
:
A fastify csrf plugin
xarray-beam
:
Distributed Xarray with Apache Beam
xarray_leaflet
:
An xarray extension for tiled map plotting.
// repository documentation
Was this content helpful?
★ 0
(0 ratings)
Select Rating:
★
★
★
★
★
Submit Feedback
Recent Feedback
×
Download README
Do you want to download the
README.md
file for
bili_danmu
?
Download (.md)
## bilibili 直播弹幕机 [](https://codecov.io/gh/qydysky/bili_danmu) [](https://app.fossa.com/projects/git%2Bgithub.com%2Fqydysky%2Fbili_danmu?ref=badge_small) [](https://r.qydysky.org/bili) [](http://bilirec.qydysky.org:10000/web/)   <a href="https://github.com/qydysky/bili_danmu/graphs/contributors"> <img src="https://contrib.rocks/image?repo=qydysky/bili_danmu&max=36" /> <div>see more</div> </a> ### 当前支持显示/功能 ### 支持OS 本程序由纯golang构建,详见[https://go.dev/wiki/MinimumRequirements#operating-systems](https://go.dev/wiki/MinimumRequirements#operating-systems) #### 当前支持显示 以下内容可能过时,点击查看[当前支持显示](https://github.com/qydysky/bili_danmu/blob/master/Reply/Msg.go#L13) - [x] 人气 - [x] 天选之人开始 - [x] 天选之人获奖 - [x] 直播间关注提示 - [x] 大航海购买 - [x] 节奏风暴 - [x] 大航海进入 - [x] 弹幕 - [x] 房间信息分区改变 - [x] 禁言 - [x] 礼物 - [x] 封禁 - [x] 下播 - [x] 开播 - [x] SC - [x] 排行榜 #### 当前支持功能 以下内容可能过时,点击查看[功能配置](https://github.com/qydysky/bili_danmu/blob/master/main/config/config_K_v.json) - [x] 直播流、弹幕回放服务 - [x] 每天自动发送将要过期的银瓜子礼物(默认发送3天内过期的) - [x] 保持当前已点亮的粉丝牌总是点亮 - [x] 银瓜子自动兑换硬币 - [x] 发进房弹幕(可选有无粉丝牌(可选每日首次发送后不发)) - [x] 每日签到 - [x] 自定义私信 - [x] 自动切换粉丝牌 - [x] 扫码登录(qrcode in webServer and cmd) - [x] 自定义语音提醒 - [x] 营收统计 - [x] 舰长数统计 - [x] 直播流、弹幕保存 - [x] ASS字幕生成 - [x] 节奏提示 - [x] 反射型弹幕机 - [x] 自动型弹幕机 - [x] 相同弹幕合并 - [x] 重复度高弹幕屏蔽 - [x] 弹幕开头字符相同缩减 - [ ] GTK信息窗(在v0.20.4移除) - [ ] GTK弹幕窗(在v0.20.4移除) #### 其他特性 - [x] 使用http,https,socks5代理 - [x] cookie加密 - [x] 弹幕自动重连(30s无响应) - [x] 直播流开播自动下载、断流再保存、故障转移、移除历史 - [x] 指定弹幕、标题切换重启录制 - [x] 命令行支持房间切换、弹幕发送、表情发送、启停录制、重载弹幕、查看历史记录、查看正在直播的主播、退出房间 - [ ] GTK信息窗支持房间切换、弹幕格式化发送、时长统计(在v0.20.4移除) - [ ] GTK弹幕窗支持自定义人/事件消息停留(在v0.20.4移除) ### 说明 本项目使用github action自动构建,构建过程详见[yml](https://github.com/qydysky/bili_danmu/blob/master/.github/workflows/go.yml) 关于离线构建,详见章节`运行`及其`注意事项` #### 指定房间回调 在(>v0.20.19),添加了`指定房间回调`配置项。 在(>v0.21.5),`指定房间回调`配置项添加了`loginChange`,当登陆状态变化时触发对应的命令。 其扩展了原配置项`指定房间录制回调`,`指定房间录制回调`将失效。 ```json { "指定房间回调":[ { "roomid-help": "指定房间号,0时禁用", "roomid":0, "runDir-help": "命令执行目录,为空时为本程序所在目录", "runDir": "", "begin-help": "当开播时触发命令", "begin": [], "fin-help": "当下播时触发命令", "fin": [], "titleChange-help": "当房间标题变化时触发,占位符{oldTitle}:旧标题(string) {newTitle}:新标题(string)", "titleChange": [], "afterRec-help": "当结束录制后(包含切片)触发对应的命令,占位符{liveDir}:录播所在目录(string)(末尾有/) {recSec}:录制时长秒数(uint)(>=0) {type}:视频类型(string)(例如mp4)", "afterRec":[], "loginChange-help": "当登陆状态变化时触发对应的命令,占位符{newState}:新的状态(string)(true/false)", "loginChange":[] } ] } ``` 从`指定房间录制回调`升级,此处使用linux示例: ```json { "durationS":60, "after":["ffmpeg","-i","0.{type}","-y","-c","copy","1.{type}"] } ``` -> ```json { "runDir": "/xxxx/", "afterRec":["./a.sh", "{liveDir}", "{recSec}", "{type}"] } ``` ```sh /xxxx/a.sh #!/bin/bash if [ "$2" -gt 60 ]; then cd $1 ffmpeg -i 0.$3 -y -c copy 1.$3 fi ``` #### 节目单 添加节目单功能(>v0.20.3),用于将多个**按顺序的无缝录播目录**组合。 这里的无缝,指由`分段时长min`、` cut`指令等切分的片段。而非重启录制的离散片段。 以下为例子: 假定当前位于`直播流保存位置`,当目录存在如下文件`1.json`时: ``` ./a/ ./a/2025_11_02-18_36_31-47867-10000-a1692e-7px/ ./a/2025_11_02-18_37_17-47867-10000-a1692e-z4h/ ./a/1.json ``` `1.json`将目录中的`2025_11_02-18_36_31-47867-10000-a1692e-7px`,`2025_11_02-18_37_17-47867-10000-a1692e-z4h`组合。 1.json: ```json [ { "name": "C", // 显示在标题 "path": "123", // 虚拟路径,不能重复 "cuts":[ // 自定义切片 { "title": "切片", //切片名 "liveDir": "", // 可选,当不为空时,时刻(st、dur)从指定的实际录播目录(与lives.liveDir相同)开始算起。否则默认从这整个集合开始算起 "st": "10s", // 起始时刻,为空时从头开始 "dur": "10s", // 时长,为空时播放到末尾 "et": "20s" // 终止时刻,为空时播放到末尾,当dur不为空时,dur优先 } ], "lives": [ // 组成该路径的录播目录 { "liveDir": "2025_11_02-18_36.*", // 实际录播目录,相对路径,开头无需./,结尾无需/。支持正则(>v0.20.11),仅单一匹配时可正常工作 "StartT": "" // 该段开始时刻,为空时从头开始,仅对于第一个子录播文件有效 }, { "liveDir": "2025_11_02-18_37_17-47867-10000-a1692e-z4h", "Dur": "" // 该段结束时长,为空时播放到末尾,仅对于最后的子录播文件有效 } ] } ] ``` 访问`http://{Web服务地址}{直播Web服务路径}?ref=a/`时,[直播流回放Web服务](#直播流回放Web服务) 的呈现:  说明: - 主播名、画质、开始时间、本场开始时间 将从第一个录播目录元数据`0.json`中获取 - 观看人数取指定组成中的最大值 - 录制时长为指定组成的时长 - 自定义切片将显示在`切片/模式`最前面,后面为指定组成中根据`弹幕分值`配置计算的切片 - 时间格式使用[time.ParseDuration](https://pkg.go.dev/time#ParseDuration)进行转换。例:`1m`为1分钟、`1h2m`为1小时2分。 #### 实时回放预处理 添加配置项`实时回放预处理`(>v0.18.8),用于在播放实时流时,返回流前,先进行处理,使用stdin和stdout,可能引入播放延迟及cpu占用 下述为在linux下使用[ffmpeg](https://ffmpeg.org/)进行预处理的例子 ```json { "实时回放预处理-help":"对实时回放流进行处理,当key以_开头时,将不会显示在streamMode接口", "实时回放预处理": { "_novidio-help": "仅返回音频流", "novidio": { "mp4":["ffmpeg","-loglevel","error","-f","mp4","-i","pipe:","-f","lavfi","-i","color=c=black","-map","0:a","-acodec","copy","-map","1:v","-vcodec","h264","-g","30","-f","mp4","-movflags","frag_keyframe+empty_moov+default_base_moof","pipe:"], "flv":["ffmpeg","-loglevel","error","-f","flv","-i","pipe:","-f","lavfi","-i","color=c=black","-map","0:a","-acodec","copy","-map","1:v","-vcodec","h264","-g","30","-f","flv","pipe:"] }, "_onlykey-help": "仅返回关键帧流", "onlykey": { "mp4":["ffmpeg","-loglevel","error","-f","mp4","-i","pipe:","-bsf:v","noise=drop=not(key)","-c","copy","-f","mp4","-movflags","frag_keyframe+empty_moov+default_base_moof","pipe:"], "flv":["ffmpeg","-loglevel","error","-f","flv","-i","pipe:","-bsf:v","noise=drop=not(key)","-c","copy","-f","flv","pipe:"] } } } ``` 说明: - `"-loglevel","error"` 隐藏其他输出 - `"-g","30"` 每30帧一个关键帧,加快加载 新增接口`http://{Web服务地址}{直播Web服务路径}streamMode`(>v0.18.8),返回上述`实时回放预处理`中不以`_`开头的键值 ```json { "code": 0, "message": "ok", "data": [ "novidio", "onlykey" ] } ``` 当请求`http://{Web服务地址}{直播Web服务路径}stream?ref=now&modeq={实时回放预处理键值}`时(>v0.18.8),将会根据当前流类型,自动调用命令,并通过stdin输入直播流,将stdout输出到返回 #### 等待同配置其他服务停止 添加配置项`stop路径`、`停止其他服务超时`(>v0.16.3)。 当配置了`Web服务地址`及`stop路径`之后,将在启动时,检测是否存在同`Web服务地址`+`stop路径`的服务,并先尝试停止它。 1. 这可以在容器启动时,优雅的停止同配置其他服务。 2. 添加命令行参数`-stop`(>v0.16.3),用于停止服务。 以下是k8s在退出时,优雅的停止服务示例[k8s pod-termination 文档](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination): ``` yml apiVersion: v1 kind: Pod metadata: name: lifecycle-main spec: containers: - name: lifecycle-main-container image: bili lifecycle: preStop: exec: command: ["/bin/sh","-c","main -stop"] ``` #### 环境变量覆盖配置项 添加配置项`从环境变量覆盖`(>v0.14.26)。将在配置文件都加载后,用环境变量覆盖配置项。 - `key`为配置键名(例如:`Web服务地址`),为空时将忽略。 - `type`为类型,可选`string`,`bool`,`float64`。为空(默认)为`string`。当为`int`等类型时,也填为`float64` - `env`为env名(例如:`addr`),为空时将忽略。 例子: ```json config_K_v.json { "Web服务地址":"0.0.0.0:20000", "从环境变量覆盖": [ { "key": "Web服务地址", "env": "addr" } ] } ``` 在当前命令行配置临时环境变量(此处为linux例子),并启动: ```sh export addr=0.0.0.0:22000 ./main -ckv config_K_v.json ``` 启动后,程序将监听22000端口而非20000端口 注意: - 当要配置的键为数组时,使用`a.[n]`表示第n个,n为非负整数。当数组长度小于n时,将忽略。 - 当要配置的键为map时,使用`a.b`表示a下的b键。当b不存在时,将忽略。 - 注意核对配置的类型是正确的,否则可能会导致配置无效。 #### cookie自定义位置 配置文件添加配置项`cookie路径`(>v0.14.26),默认为`./cookie.txt` #### 获取视频切片 当请求`http://{Web服务地址}{直播Web服务路径}stream?ref={录播文件夹名}&st={起始时间}&dur={片段时长}`时,将返回从录播文件的切片视频(>v0.14.21) 切片将从大于`{起始时间}`的关键帧开始,`{片段时长}`之后的关键帧结束,故大多数情况不能获得精确时间的切片视频 切片不会进行渲染,仅参考文件中的时间戳进行切片 其中`dur`为空时,将返回全部时长。`st`参数可以为空或不传,此时从录播文件起始点开始。 `{起始时间}`、`{片段时长}`格式使用[time.ParseDuration](https://pkg.go.dev/time#ParseDuration)进行转换。例:`1m`为1分钟、`1h2m`为1小时2分。 注意:当配置`直播流回放连接检查`启用时(默认不启用),你需要配置`直播流回放连接检查忽略key`(>v0.14.21)以避免检查,url加上参数`&key={配置的key}`。 例子: ```json { "Web服务地址":"0.0.0.0:20000", "直播Web服务路径":"/web/", "直播流回放连接检查": 10, "直播流回放连接检查忽略key-help": "字符串数组,默认空,空字符串将忽略,当不为空时,将不会定时检查指定key值的请求", "直播流回放连接检查忽略key": ["cut"], } ``` ``` curl -v "http://192.168.31.230:20000/web/stream?ref=2024_11_04-01_29_47-47867-250-edd590-JdB&key=cut&dur=1m" * Trying 192.168.31.230:20000... * Connected to 192.168.31.230 (192.168.31.230) port 20000 > GET /web/stream?ref=2024_11_04-01_29_47-47867-250-edd590-JdB&key=cut&dur=1m HTTP/1.1 > Host: 192.168.31.230:20000 > User-Agent: curl/8.9.1 > Accept: */* > * Request completely sent off < HTTP/1.1 200 OK < Access-Control-Allow-Credentials: true < Access-Control-Allow-Headers: * < Access-Control-Allow-Methods: POST, GET, OPTIONS < Access-Control-Allow-Origin: * < Connection: keep-alive < Content-Disposition: inline; filename="2024_11_04-01_29_47-47867-250-edd590-JdB.1731342591.mp4" < Content-Transfer-Encoding: binary < Content-Type: video/mp4 < Date: Mon, 11 Nov 2024 16:29:51 GMT < Transfer-Encoding: chunked < Warning: Binary output can mess up your terminal. Use "--output -" to tell curl to output it to your terminal anyway, or consider "--output <FILE>" to save to a file. * client returned ERROR on write of 1004 bytes * Failed reading the chunked-encoded stream * closing connection #0 ``` 添加快速索引文件生成,将在录制完成后,自定义回调命令执行前,读取视频文件,并将关键帧的时间戳和对应的下标值记录在`.fastSeed`文件,用于加快后续切片请求响应。(>v0.14.28) 可以设置`禁用快速索引生成`(默认为`false`)为`true`来禁用这个动作(>v0.14.28) 相较于之前的请求时进行查找,效率提升如下 ``` mp4: 旧: // 10s-30s 110.962896ms // 10m-10m20s 1.955749395s // 30m-30m20s 5.791614855s 新: // 10s-30s 90.05983ms // 10m-10m20s 88.769475ms // 30m-30m20s 104.381225ms flv: 旧: // 10s-30s 184.852917ms // 10m-10m20s 3.278605875s 新: // 10s-30s 215.815423ms // 10m-10m20s 174.918508ms ``` `.fastSeed`文件格式: ``` +--------+-----------+ |Ms int64|index int64| +--------+-----------+ |8bytes |8bytes | +--------+-----------+ Ms:毫秒时间戳 index:相对于文件起始位置的byte下标值 文件由n组上述16bytes组成,时间戳升序 ``` #### Web自定义响应头 配置文件中添加配置项`Web自定义响应头`(>v0.14.19)。默认为空,当不为空时,将在所有响应中添加指定头。 例子: ``` { "Web服务地址":"0.0.0.0:11000", "直播Web服务路径":"/web/", "Web自定义响应头": { "Access-Control-Allow-Origin":"*" } } ``` ``` curl -i http://{主机名}:11000/web/emots/4e9621239e8a349b1ad198af90458e06.png HTTP/1.1 200 OK Access-Control-Allow-Origin: * Cache-Control: private Etag: 2024-09-24T01:53:03+08:00 Last-Modified: Tue, 24 Sep 2024 01:53:03 CST Date: Sat, 05 Oct 2024 14:02:18 GMT Content-Type: image/png Transfer-Encoding: chunked ``` #### ip路径 配置文件中添加配置项`ip路径`(>v0.14.16)。不为空时,将会在指定路径显示出当前主机ip,从而可以使用主机名来获取主机ipv6,以便于[ddns-go](https://github.com/jeessy2/ddns-go)等通过命令获取ipv6。默认空。 例子: ``` { "Web服务地址":"0.0.0.0:11000", "ip路径":"/ip/" } ``` ``` curl -s http://{主机名}:11000/ip/ 192.168.31.230 172.16.0.1 172.17.144.244 172.17.0.1 172.17.0.10 172.17.121.35 2409:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:8ce5 fd55:d4a5:a9e7:0:aab8:e0ff:fe03:8ce5 fe80::aab8:e0ff:fe03:8ce5 fe80::d8dc:35ff:fe21:d71b fe80::785f:8dff:fe34:9443 fe80::440a:9fff:fe6d:5da6 fe80::60ff:4cff:fee7:c226 fe80::4c24:e3ff:fe65:b955 fe80::8099:ecff:fefa:f36c fe80::68fe:63ff:fe74:6e35 ``` ``` curl -s http://{主机名}:11000/ip/ | awk '/240:?/' 2409:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:8ce5 ``` #### 保持粉丝牌点亮 (>0.17.1)保持粉丝牌功能修改为仅对当前直播间生效。以避免,在当前规则下,对于持有大量牌子将会频繁发送弹幕。 取消配置项`保持牌子亮着_指定时间`。 默认只在下播时,发送`进房弹幕_内容`的以保持亮牌,1天内将最多发送10条弹幕/30次点赞,间隔大于100s。 添加配置项`保持牌子亮着-开播时也发送`默认为false,当为true时,开播时也会发送。 #### 直播回放显示表情 配置文件中添加配置项`弹幕表情`(>v0.14.9)。默认为true,当为true时,将会保存弹幕中的表情png到emots目录下,并在回放时显示表情。 为了能顺利保存,存储通过md5作为文件名,如:[dog?]=>md5("[dog?]")+".png"=>0c8427bdb9854d85e9cfe59c45d70583.png 从而避免对原表情产生修改,且避免不同环境对文件名支持的差异。 注意:需要配套更新`main/html/artPlayer`下的资源 保存的表情可以通过`http://{Web服务地址}{直播Web服务路径}emots/{md5}.png`获取。 在(>v0.16.6)中,在录制结束时,本场录制出现的表情将会从emots目录复制到录制文件夹下的`emotes.zip`中。 当请求`http://{Web服务地址}{直播Web服务路径}emots/{md5}.png`时,如请求头`Referer`中的`ref`url参数为有效的录播文件夹名,并且该文件夹下有`emotes.zip`。 则在回放中使用`emotes.zip`中的表情,这确保了录播文件夹迁移到其他环境时,即使emots目录没有对应表情,也可以正常回放表情。 #### 直播流停用服务器 配置文件中添加配置项`直播流停用服务器`(>v0.14.3)。默认为空,编写正则字符串,当获取到的服务器链接与字符串匹配时,将会停用。 ```json { "直播流不使用mcdn": false, "直播流停用服务器": [ "\\.mcdn\\." ], } ``` #### fmp4相关优化 配置文件中添加配置项`fmp4获取更多服务器`(>v0.14.2)。当直播流类型为fmp4,为`true`时,会在可用切片服务器仅剩1个时,获取更多服务器,但总数超过5个后,将不会再获取。默认为`true`。 配置文件中添加配置项`fmp4跳过解码出错的帧`(>v0.14.2)。当直播流类型为fmp4,为`true`时,会在跳过解码错误的帧(常见于音视频时间戳差过大),这将导致错误的部分缺失,时间轴发生跳越,但能获得一个完整记录。默认为`false`。 ```json { "fmp4获取更多服务器": true, "fmp4跳过解码出错的帧-help": "fmp4跳过解码出错的帧、但可能导致关键帧时间上的跳越", "fmp4跳过解码出错的帧": false, } ``` #### 自定义命令行登陆二维码块 配置文件中添加配置项`登陆二维码-白`、`登陆二维码-黑`。 默认: ```json { "登陆二维码-白":"OO", "登陆二维码-黑":" " } ``` 在某些平台,命令行可能被设置为等宽字符,此时默认配置会导致二维码显示比例错误,可以调整到: ```json { "登陆二维码-白":"OOO", "登陆二维码-黑":" " } ``` 或其他字符,或者使用浏览器打开`扫码登录路径`配置的路径进行扫码登陆 (>v0.20.3)当`扫码登陆`为`true`时,未登录时访问`扫码登录路径`触发登陆,而不用在命令行使用` login`触发 #### 指定用户弹幕切片 配置文件中添加配置项`指定弹幕重启录制`。 - `uid`:进入个人空间,可以在地址栏看到你的uid - `danmu`:正则匹配表达式 - 多个相同`uid`的规则存在时,则会覆盖,取最后一个规则,一个用户最多一条规则 - `uid`或`danmu`为""时,将忽略这个规则 当有`匹配分组`时,第一个分组将作为新标题,例:`t(.*)`,接收到`t暗潮t炒`时,则会将`暗潮t炒`作为标题。 无`匹配分组`时,将以原标题切片,例:`t`,接收到`t暗潮t炒`时,将会切片。 ```json { "指定弹幕重启录制":[ { "uid":"29183321", "danmu":"t(.*)" } ] } ``` #### 指定房间录制区间 配置文件中添加配置项`指定房间录制区间`。 指定roomid的房间在指定时间段内将会开启录制。注意:注意先配置主机时区 - `start`时检查是否在直播,是则开始录制,如已在录制则切片。 - `end`时如已在录制则停止录制。 - 存在同时有`start`,`end`的`fromTo`,则开播时,若在`start`与`end`之间,则录制。不存在同时有`start`,`end`的`fromTo`,则一开播就录制。 - 5s内只能触发一个`fromTo`,所以同房间各`start`、`end`之间间隔不要少于5s。 ```json { "指定房间录制区间":[ { "roomid":0, "fromTo":[ { "start": "12:01:00", "end": "12:03:00" }, { "start": "12:02:00" } ] } ] } ``` #### 保存日志至DB 配置文件中添加配置项`保存日志至db`。使用`{...}`占位符,而非`?`。可选字段见下方示例(>v0.14.28) ```json { "保存日志至db":{ "dbname": "postgres", "url":"postgres://postgres:qydysky@192.168.31.103:5432/postgres?sslmode=disable", "字段help":"{Date} time.Now().Format(time.DateTime), {Unix} time.Now().Unix(), {Prefix} string,{Base} string,{Msgs} string", "create":"create table log2 (created varchar(20), createdunix varchar(20), Prefix varchar(10), Base varchar(30), Msgs varchar(500))", "insert":"insert into log2 (created, createdunix, Prefix, Base, Msgs) values ({Date},{Unix},{Prefix},{Base},{Msgs})" } } ``` log: |"created" |"createdunix"|"prefix"|"base" |"msgs" | |-------|-----------|---|-----|----| |"2025-01-15 01:42:25"|"1736876545" |T: |功能 更少弹幕 |每秒弹幕数: 1 | |"2025-01-15 01:42:25"|"1736876545" |I: |功能 直播Web服务 |启动于 http://0.0.0.0:20000/web/| |"2025-01-15 01:42:25"|"1736876545" |I: |bilidanmu |当前PID: 485073 | |"2025-01-15 01:42:25"|"1736876545" |I: |bilidanmu |version: 20250105171800 | |"2025-01-15 01:42:25"|"1736876545" |I: |bilidanmu |"3s内2次ctrl+c退出" | |"2025-01-15 01:42:26"|"1736876546" |T: |api IsConnected|已连接 | |"2025-01-15 01:42:26"|"1736876546" |T: |api Get |Get Cookie | |"2025-01-15 01:42:26"|"1736876546" |I: |api 获取Cookie |已登录 | |"2025-01-15 01:42:27"|"1736876547" |T: |api Get |Get LIVE_BUVID | |"2025-01-15 01:42:27"|"1736876547" |I: |api LIVE_BUVID |获取到LIVE_BUVID,保存cookie | |"2025-01-15 01:42:27"|"1736876547" |T: |api Get |Get Uid | |"2025-01-15 01:42:27"|"1736876547" |T: |命令行操作 |回车查看帮助 | |"2025-01-15 01:42:28"|"1736876548" |T: |api 银瓜子=>硬币 |现在有银瓜子 518 个 | |"2025-01-15 01:42:28"|"1736876548" |I: |api 银瓜子=>硬币 |当前银瓜子数量不足 | |"2025-01-15 01:42:28"|"1736876548" |I: |功能 保持亮牌 |将在 00:00:00 启动 | |"2025-01-15 01:42:28"|"1736876548" |T: |指定弹幕重启录制 |加载 1 条规则 | |"2025-01-15 01:42:51"|"1736876571" |I: |bilidanmu |等待1m0s协程结束 | |"2025-01-15 01:42:51"|"1736876571" |I: |bilidanmu |结束 | #### 保存弹幕至DB 配置文件中添加配置项`保存弹幕至db`。参考以下实例: postgreSql: ```json { "保存弹幕至db": { "dbname": "postgres", "url":"postgres://postgres:qydysky@192.168.31.103:5432/postgres?sslmode=disable", "字段help":"time.Now().Format(time.DateTime), time.Now().Unix(), item.msg, item.color, item.auth, item.uid, item.roomid", "create":"create table danmu (created varchar(20), createdunix varchar(20), msg varchar(100), color varchar(20), auth varchar(50), uid varchar(30), roomid varchar(30))", "insert":"insert into danmu (created, createdunix, msg, color, auth, uid, roomid) values ({Date},{Unix},{Msg},{Color},{Auth},{Uid},{Roomid})" } } ``` mysql: ```json { "保存弹幕至db": { "dbname": "mysql", "url":"root:root@(192.168.31.103:10836)/test", "字段help":"time.Now().Format(time.DateTime), time.Now().Unix(), item.msg, item.color, item.auth, item.uid, item.roomid", "create":"create table danmu (created varchar(20), createdunix varchar(20), msg varchar(100), color varchar(20), auth varchar(50), uid varchar(30), roomid varchar(30))", "insert":"insert into danmu (created, createdunix, msg, color, auth, uid, roomid) values ({Date},{Unix},{Msg},{Color},{Auth},{Uid},{Roomid})" } } ``` sqlite3: 注意:不要并发连接数据库,可能会导致失败 ```json { "保存弹幕至db": { "dbname": "sqlite", "url":"danmu.sqlite3", "字段help":"time.Now().Format(time.DateTime), time.Now().Unix(), item.msg, item.color, item.auth, item.uid, item.roomid", "create":"create table danmu (created text, createdunix text, msg text, color text, auth text, uid text, roomid text)", "insert":"insert into danmu values ({Date},{Unix},{Msg},{Color},{Auth},{Uid},{Roomid})" } } ``` 字段`create`可以为空字符串,此时将不会在初次接收到弹幕时执行`create`语句,你必须要预先创建好表。 数据实例: |created|createdunix|msg|color|auth|uid|roomid| |-------|-----------|---|-----|----|---|------| |2023-04-26 03:20:33|1682450433|可能走位配合了他的压枪|#e33fff|畏未|96767379|92613| |2023-04-26 03:20:45|1682450445|=。=|#54eed8|青江知暖|282800070|92613| |2023-04-26 03:20:52|1682450452|这不是铁挂吗|#ffffff|瑶少溪|43048863|92613| |2023-04-26 03:20:55|1682450455|开个箱?|#58c1de|修阡宇|433678545|92613| |2023-04-26 03:20:59|1682450459|来了来了|#00fffc|我肚子是吃饱了撑大的|830140|92613| #### 指定房间录制回调 在>v0.20.19,此配置作废,你可以使用`指定房间回调`进行等效替换 配置文件添加了如下配置 ```json { "指定房间录制回调-help":"当指定roomid的房间结束录制后触发对应的命令,命令执行目录为录播目录,占位符({type}:视频类型),durationS:录制时长超过指定秒数才触发", "指定房间录制回调":[ { "例子":"windows转为正常的视频", "roomid":0, "durationS":60, "after":["cmd","/c","ffmpeg","-i","0.{type}","-y","-c","copy","-movflags","+faststart","1.{type}"] }, { "例子":"linux转为正常的视频", "roomid":0, "durationS":60, "after":["ffmpeg","-i","0.{type}","-y","-c","copy","-movflags","+faststart","1.{type}"] }, { "例子":"linux调整为统一分辨率(一个视频中出现分辨率改变eg:连麦)", "roomid":0, "durationS":60, "after":["ffmpeg","-i","0.{type}","-vf","scale=1920:1080:force_original_aspect_ratio=decrease:eval=frame,pad=1920:1080:-1:-1:color=black","1.{type}"] } ] } ``` 上述例子中演示了windows、linux下使用[ffmpeg](https://ffmpeg.org/) 进行视频转换。 注意:命令运行是异步的,如同步执行多个命令,应使用脚本。 #### 性能检查 当配置了`Web服务地址`及`性能路径`时,运行中的性能信息将可以通过http获取。 例如有如下配置: config_K_v.json ```json { ... "Web服务地址":"0.0.0.0:10000", "性能路径":"/state/" ... } ``` 此时GET http://127.0.0.1:10000/state/ ```json { "code": 0, "message": "ok", "data": { "common": { "92613": { // 房间号 "live": [ { "host": "cn-jssz-cm-02-05.bilivideo.com", // 流服务器主机名 "up": true, // 是否启用 "codec": "avc", // 编码格式 "createTime": "2025-09-02T18:18:22+08:00", // 流服务器最初启用时间 "reUpTime": "0001-01-01T00:00:00Z", // 流服务器启用时间 "expires": "2081-05-05T05:36:44+08:00", "disableCount": 0 // 禁用次数 }, { "host": "d1--cn-gotcha204b.bilivideo.com", "up": true, "codec": "avc", "createTime": "2025-09-02T18:18:22+08:00", "reUpTime": "0001-01-01T00:00:00Z", "expires": "2081-05-05T05:36:44+08:00", "disableCount": 0 } ], "liveQn": 10000, // 画质编码 "title": "国际服在开荒一两天", // 房间标题 "uname": "少年Pi", // 主播名 "upUid": 13046, // 主播id "rev": 1812.4, // 本场营收 "watched": 41456, // 本场观看人数 "onlineNum": 172, // 当前在线人数 "guardNum": 530, // 大航海人数 "parentAreaID": 6, // 分区编码 "areaID": 235, // 子分区编码 "locked": false, // 直播间是否被封禁 "login": true, // 当前服务是否登陆 "note": "人气榜 100+", // 排名 "liveStartTime": "0001-01-01T00:00:00Z", // 本场开始直播时间 "liveing": false // 当前是否在直播 } }, "gc": { "gcAvgS": 117.19, // 平均gc间隔 "gcCPUFractionPpm": 10.23, // gc消耗cpu时间占比,百万分之 "lastGC": "2025-09-03T09:37:34+08:00", // 上次gc时间 "numGC": 970 // 总gc次数 }, "goVersion": "go1.25.0 X:jsonv2,greenteagc", // 构建golang版本 "mem": { "memInUse": "20 MB", // 当前正在使用的内存大小 "memTotalAlloc": "9.1 GB" // 申请的内存历史总计数 }, "numGoroutine": 22, // 当前协程数 "pid": 2729, // pid "reqPoolState": { "inuse": 0, // 请求池当前使用数量 "nopooled": 0, // 请求池未在池中数量 "nouse": 4, // 请求池当前未使用数量 "pooled": 4, // 请求池在池中数量 "qts": 0.1, // 请求池每秒使用次数 "sum": 4 // 请求池大小 }, "timeInfo": { "biliServerTimeZone": 28800, // bilibili服务器时区,单位秒 "currentTime": "2025-09-03T09:38:03+08:00", // 服务当前时间 "startTime": "2025-09-02T02:03:23+08:00", // 服务启动时间 "timeZone": 28800 // 服务时区 }, "version": "2887d35" // 服务版本 git commit } } ``` 另外,当配置文件中的`debug路径`不为空时, 访问此路径可以获取调试信息,为空时关闭,需要/结尾,默认为空 - 标准包[net/http/pprof](https://pkg.go.dev/net/http/pprof)将在`debug路径`路径可用,从而可以使用`go tool pprof`工具进行性能调试。 另外,当配置文件中的`debug模式`为`true`时,默认为`false`, 启用额外调试信息 - 当录制fmp4时,每1分钟打印m4s池状态 #### 自定义config_K_v.json 当启动时使用`-ckv 路径`,将从此路径(或http地址)加载config_K_v.json并覆盖默认config_K_v.json中的配置项。 使用此配置,可以在有新配置项时,默认使用新配置项而保持之前其他的配置。 #### 表情发送 当`main/config/config_K_v.json`中`弹幕_识别表情代码`为`true`时,发送特定的文字将发送表情。 在`main/config/config_danmu_official.json`中可找到支持的特殊文字 如,命令行输入点赞回车: ``` 点赞 I: 2022/09/15 02:23:21 弹幕发送 [发送 official_147 至 92613] 赞 ``` danmu.log ``` I: 2022/09/15 02:23:21 弹幕发送 [发送 official_147 至 92613] I: 2022/09/15 02:23:23 Msg [qydysky丶 : 赞] ``` #### 流保存、弹幕ass、弹幕回放文件 以下内容可能过时,点击查看[配置](https://github.com/qydysky/bili_danmu/blob/master/main/config/config_K_v.json#L55) ```json "直播流清晰度-help": "清晰度可选-1:不保存 0:默认 20000:4K 10000:原画 400:蓝光 250:超清 150:高清 80:流畅,无提供所选清晰度时,使用低一档清晰度", "直播流清晰度": 400, "直播流类型-help": "flv,fmp4,flvH,fmp4H,fmp4A,带H后缀的为Hevc格式编码,带A后缀的为av1格式编码", "直播流类型": "flv", "直播流保存位置": "./live", "直播hls流故障转移-help":"true:hls服务器故障时,使用其他", "直播hls流故障转移": true, "直播hls流保存为MP4": true, "仅保存当前直播间流-help": "启用此项,才会保存Ass", "仅保存当前直播间流": true, "直播Web服务口":10000, "直播Web缓冲长度-help":"非负整数,越长直播流延迟越高 内存占用越高", "直播Web缓冲长度":5, "直播Web可以发送弹幕":true, "弹幕回放-help": "仅保存当前直播间流为true时才有效", "弹幕回放": true, "ass-help": "只有保存直播流时才考虑生成ass,ass编码默认GB18030(可选utf-8)", "生成Ass弹幕": true, "Ass编码": "GB18030", ``` 当直播流类型为`fmp4`或`fmp4H`或`fmp4A`(>v0.20.6)时,默认将下载的切片合并保存为mp4。 当所选类型在当前直播中不可用时,会按以下顺序[`fmp4`,`flv`,`fmp4H`,`flvH`,`fmp4A`]尝试。 Ass默认`utf-8`编码,在录播结束时生成,可以配合`指定房间回调`生成硬编码弹幕的视频,配置项如下(>v0.15.9) ```json { "指定房间回调":[ { "roomid-help":"0替换为指定的房间号", "roomid":0, "afterRecSec":10, "afterRec":["ffmpeg","-i","{liveDir}0.{type}","-y","-vf","ass=0.ass","{liveDir}1.{type}"] } ], "Ass": { "fontname-help":"指定字体", "fontname":"", "fontsize-help":"字体大小int", "fontsize":40, "showSec-help":"弹幕显示时长int,秒", "showSec":10, "area-help":"弹幕显示区域,float64,0-1(全屏)", "area":1.0, "alpha-help":"弹幕透明度,float64,0(不透明)-1(透明)", "alpha":1.0 } } ```  弹幕回放(仅直播流Web服务) 在保存直播流时,如`弹幕回放`为`true`,则会将会将弹幕同时保存为csv文件。切片或停止录制时,根据csv文件生成[xml文件](https://socialsisteryi.github.io/bilibili-API-collect/docs/danmaku/danmaku_xml.html#xml%E5%BC%B9%E5%B9%95) 在[直播流Web服务](#直播流Web服务)中,点击进入任意一个目录,进行回放,如`弹幕回放`为`true`,则会将会将弹幕回放出来。 添加配置项`弹幕回放_隐藏发送人`(>v0.14.19),为`true`时,回放弹幕文件类型记录(ass,xml,csv...)不记录发送人,当前直播的即时回放不显示发送人,但不影响`保存弹幕至db`等日志类型记录。由于回放依赖于csv类型文件,故回放历史录播亦不显示发送人。默认为`false`。 添加配置项`弹幕回放_未登录时隐藏发送人`(>v0.20.3),由于隐私设置,未登录时发送人被打码,当此项为`true`时,未登录不会录制发送人。默认为`true`。 当`直播流保存天数`大于1时(默认4),当t日有1录播时,会尝试删除t-n日及之前的1or2个最早的录播。目录下有.keep文件或目录名不以`yyyy_mm_dd-hh24_mi_ss`开头将忽略(v0.12.7+)。 #### 直播流回放Web服务 启动Web流服务,为下载的直播流提供局域网内的流服务,提供flv、hls/mp4格式流。 在`main/config/config_K_v.json`中可找到配置项,`0.0.0.0`:开放至局域网 `127.0.0.1`:仅本机。 ``` "Web服务地址":"0.0.0.0:10000", "直播Web服务路径":"/web/", ``` 下述路径以上面这个配置作为实例。 直接进入直播Web服务路径,`http://127.0.0.1:10000/web/`,将进入由[Vue](https://vuejs.org/),[element-plus](https://element-plus.org/)创建的简易web目录。 添加`ref`参数,从而可以从指定位置加载目录(>v0.14.27)。 例如: ```json { "直播流保存位置":"/bili" } ``` 当有录播文件夹存放在`/bili/a`时,通过`http://127.0.0.1:10000/web/?ref=a/`可以读取`a`下的列表 [https://github.com/qydysky/bili_danmu_streamList](https://github.com/qydysky/bili_danmu_streamList)  点击目录项,将进入由[artplayer](https://artplayer.org/)、[mpegts](https://github.com/xqq/mpegts.js)创建的简易回放界面 [https://github.com/qydysky/bili_danmu_artplayer](https://github.com/qydysky/bili_danmu_artplayer)  **特殊** - 路径为`http://127.0.0.1:10000/web/stream?ref=now` 当前正在获取的流,播放此链接时进度将保持当前流进度,在登陆情况下,可以发送弹幕。流格式为fmp4(Hevc、AV1(>v0.20.6))或flv(Hevc) 使用`?ref={目录}`参数来获取流,当为`?ref=now`时,为当前直播流 - Hevc、Av1(>v0.20.6)格式,可能需要硬件解码支持 - 预览[92613少年Pi的直播回放](https://r.qydysky.org/bili),此预览地址已应用如下配置 <details> <summary>config_K_v.json</summary> ```json { "ip路径":"/xxxxxxx/", "日志文件输出-help": "为空时不保存日志", "日志文件输出": "", "指定弹幕重启录制":[ { "uid":"29183321", "danmu":"1" } ], "弹幕输出到日志": false, "直播流清晰度-help": "清晰度可选-1:不保存 0:默认 20000:4K 10000:原画 400:蓝光 250:超清 150:高清 80:流畅,无提供所选清晰度时,使用低一档清晰度", "直播流清晰度": 10000, "直播流类型-help": "flv,fmp4,flvH,fmp4H,带H后缀的为Hevc格式编码", "直播流类型": "fmp4", "直播流保存位置": "/bilirec", "Web服务地址":"0.0.0.0:10000", "直播Web服务路径":"/web/", "直播Web可以发送弹幕":false, "直播流不使用mcdn":false, "fmp4获取更多服务器": true, "fmp4跳过解码出错的帧": true, "flv使用内置头": true, "直播流回放速率": "3 MB", "分段时长min": 60, "标题修改检测s": 1200, "直播流回放连接检查": 100, "Web服务连接限制": [ { "cidr":"0.0.0.0/0", "max":10 } ], "直播流回放连接限制": [ { "help":"内网网段", "cidr":"192.168.31.1/24", "max":-1 }, { "help":"公网网段", "cidr":"127.0.0.1/32", "max":2 }, { "help":"公网网段", "cidr":"::/0", "max":2 } ], "cookie保护": "下填路径", "cookie加密公钥": "public.pem", "cookie解密私钥": "private.pem", "debug模式-help":"启用额外调试信息", "debug模式":true, "debug路径-help":"当Web服务地址不为空时, 访问此路径可以获取调试信息,为空时关闭,需要/结尾", "debug路径":"/xxxxxxx/", "生成pgo":"", "扫码登录":true, "保存弹幕至db": { "dbname": "postgres", "url":"postgres://postgres:qydysky@192.168.31.103:5432/postgres?sslmode=disable", "字段help":"time.Now().Format(time.DateTime), time.Now().Unix(), item.msg, item.color, item.auth, item.uid, item.roomid", "create":"create table danmu (created varchar(20), createdunix varchar(20), msg varchar(100), color varchar(20), auth varchar(50), uid varchar(30), roomid varchar(30))", "insert":"insert into danmu (created, createdunix, msg, color, auth, uid, roomid) values ({Date},{Unix},{Msg},{Color},{Auth},{Uid},{Roomid})" }, "保存日志至db":{ "dbname": "postgres", "url":"postgres://postgres:qydysky@192.168.31.103:5432/postgres?sslmode=disable", "字段help":"$1:Prefix $2:Base $3:Msgs, use ? or $%d not placeholder", "create":"create table log (created timestamp, Prefix varchar(10), Base varchar(30), Msgs varchar(500))", "insert":"insert into log (created, Prefix, Base, Msgs) values (now(),$1,$2,$3)" }, "服务器时区":28800, "弹幕表情": true } ``` </details> 测试可用项目(测试可连续播放10min+): - flv-html播放器 - [xqq/mpegts.js](https://github.com/xqq/mpegts.js) - hls-html播放器 - [bytedance/xgplayer](https://github.com/bytedance/xgplayer) - [videojs/video.js](https://github.com/videojs/video.js)([main](https://videojs-http-streaming.netlify.app)) - [video-dev/hls.js@v1.0.7+](https://hls-js-10780deb-25d8-41d3-b164-bc334c8dd47f.netlify.app/main/) - mp4-html播放器 - [bytedance/xgplayer](https://github.com/bytedance/xgplayer) - [videojs/video.js](https://github.com/videojs/video.js)([main](https://videojs-http-streaming.netlify.app)) - 客户端播放器 - [mpv](https://mpv.io/) - [MXPlayer](https://sites.google.com/site/mxvpen/home) #### 命令行操作 在(>v0.21.5)在登陆状态时可以使用` logout`登出当前cookie。 在准备动作完成(`T: 2021/03/06 16:22:39 命令行操作 [回车查看帮助]`)后,输入回车将显示帮助 ``` 切换房间->输入' 数字'回车 发送弹幕->输入'字符串'回车 查看直播中主播->输入' liv'回车 重载弹幕->输入' reload'回车 搜索主播->输入' sea关键词'回车 房间信息->输入' room'回车 开始结束录制->输入' rec'回车 退出当前房间->输入' exit'回车 其他输出隔断不影响 ``` 用例: - 直播间切换 ``` his T: 2023/02/01 02:34:00 命令行操作 [指令( his)] T: 2023/02/01 02:34:00 api 历史直播主播 [获取中] T: 2023/02/01 02:34:00 api 历史直播主播 [完成] 0 ☁ 少年Pi(92613) MC 1 C酱です(47867) 阿C今天又在玩什么捏 2 逍遥散人(1017) 日常闲聊 麻将上分训练 3 烤鱼子Official(22259479) !!!!新年快乐!!!! 4 ☁ Asaki大人(6154037) 开心鸭鸭杀 5 观察者网(948391) 一周军情观察:海的那边是敌人 6 一米八的坤儿(4350043) 单排下饭主播 7 数字猫(3839755) 石村号上的朋友真是热情好客 8 ☁ 环球时报(796281) 家乡的风景 家乡的年 9 千鈴鳴_Official(26724557) 【B限】原神やるぞおおおお【千鈴鳴】 回复' to(序号)'进入直播间 3 x 9 满脑子都是小c to4 T: 2023/02/01 02:34:07 命令行操作 [指令( to4)] I: 2023/02/01 02:34:07 bilidanmu [停止,等待服务器断开连接] I: 2023/02/01 02:34:07 bilidanmu [服务器连接关闭] I: 2023/02/01 02:34:07 直播流保存 [正在等待下载完成...] T: 2023/02/01 02:34:08 弹幕回放 [停止] I: 2023/02/01 02:34:08 直播流保存 [结束录制(92613)] T: 2023/02/01 02:34:09 功能 弹幕合并 [房间更新: 6154037] T: 2023/02/01 02:34:09 bilidanmu [准备] T: 2023/02/01 02:34:09 api IsConnected [已连接] I: 2023/02/01 02:34:10 bilidanmu [连接到房间 6154037] I: 2023/02/01 02:34:16 api 切换粉丝牌 [无主播粉丝牌] I: 2023/02/01 02:34:17 bilidanmu [直播中] T: 2023/02/01 02:34:17 bilidanmu [连接 wss://hw-sh-live-comet-03.chat.bilibili.com/sub] I: 2023/02/01 02:34:17 bilidanmu [已连接到房间 Asaki大人 ( 6154037 )] I: 2023/02/01 02:34:17 bilidanmu [开心鸭鸭杀] T: 2023/02/01 02:34:18 bilidanmu [获取人气] ``` ``` 120 I: 2021/03/06 16:21:35 命令行操作 [进入 120] ``` - 发送弹幕 ``` 1 I: 2021/03/06 16:21:17 弹幕发送 [发送 1 至 7734200] ``` - 查看房间信息 ``` room T: 2023/02/01 02:35:38 命令行操作 [指令( room)] 当前直播间(6154037)信息 Asaki大人 开心鸭鸭杀 直播中 已直播时长: 08:12:18 营收: ¥0.00 舰长数: 1287 分区排行: 人气榜 2 人气: 2049772 观看人数: 278848 在线人数: 10000 直播Web服务: http://0.0.0.0:10000 正在录制的房间: Asaki大人(6154037) 开心鸭鸭杀 输入` rec` 来启停当前房间录制 ``` 还支持登录、搜索主播直播间、查看历史记录、查看关注的直播间、保存直播流等功能 #### cookie加密 在(>0.16.9),添加对于`mlkem`的算法支持,`-genKey`默认将产生`mlkem`算法公私钥。保留对`X25519`算法(<=0.16.9)产生的cookie加解密的支持,`main/`下的(public.pem)(private.pem)默认更新为`mlkem`格式。 如需更新密钥(如从`X25519`转换到`mlkem`),而不重新登陆,参考如下步骤: - 在非正式环境,使用`-genKey`命令行参数生成新密钥。注:此命令行参数仅需要主程序(如`main`/`main.exe`),无需其他资源文件即可生成 - 拷贝步骤1命令行打印的新公钥到正式环境的`cookie加密公钥`文件 - 确保你正式环境的主程序版本已大于>0.16.9 - 启动正式环境程序,这将使用旧私钥读取cookie并用新公钥加密cookie - 拷贝步骤1命令行打印的新私钥到正式环境的`cookie解密私钥`文件 - 更新完成 *使用X25519和chacha20poly1305*(>v0.14.15) 保护cookie.txt 在`main/config/config_K_v.json`中可找到配置项 ``` "cookie加密公钥":"public.pem", "cookie解密私钥":"private.pem" ``` - 当配置了公钥路径后,cookie将被加密(若公钥无效,将会导致cookie无法储存)。若未配置私钥路径,则每次启动都会要求输入私钥路径。(若私钥无效,将会导致cookie被清除) - 当未配置公钥路径(空字符串),cookie将明文储存。 - 默认使用了`main/`下的(public.pem)(private.pem)进行加密,使用时注意自行生成公私钥并按照上述说明使用 注意,每次更换设置(设置或未设置公钥),cookie会失效。 附:创建公(public.pem)私(private.pem)钥 ``` 使用 -genKey 生成(>v0.14.15) main(main.exe) -genKey 公钥: -----BEGIN MLKEM PUBLIC KEY----- 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 -----END MLKEM PUBLIC KEY----- 私钥: -----BEGIN MLKEM PRIVATE KEY----- 6lJ+OzINP4QmpqKFtlCi5lFHaYneWpfjBkU6xlnrlmMCFBRn1tlYQVf91HT9IOEh kuDE/k1SerQNHYP7oBVRsw== -----END MLKEM PRIVATE KEY----- 请复制以上公私钥并另存为文件,可以在cookie加密公钥、cookie解密私钥中使用 ``` #### 私信 在登录后,可以使用私信 私信配置在`main/config/config_K_v.json`有说明 #### 语音 调用tts默认使用ffplay,安装[ffmpeg](http://ffmpeg.org/download.html) 或使用其他程序:可在`main/config/config_K_v.json`中编辑调用的程序及附加选项 ``` config_K_v.json 默认 "TTS_使用程序路径":"ffplay", "TTS_使用程序参数":"-autoexit -nodisp" 使用mpv "TTS_使用程序路径":"mpv", "TTS_使用程序参数":"--no-video" 使用potplayer(例程序位置D:\potplayer\PotPlayerMini64.exe) "TTS_使用程序路径":"D:\\potplayer\\PotPlayerMini64.exe", "TTS_使用程序参数":"/current /autoplay" ``` release默认编译tts 总开关,自定义响应的事件可在`main/config/config_tts.json`中编辑。{}为传递过来的变量,将会按设定替换。最后未使用的{}会全部删除。下例:`ABC购买 1个月舰长`。 ``` ... "0buyguide-help": "大航海 {username}:用户 {op_name}:购买方式 {role_name}:大航海类型 {num}:个数 {unit}:时间单位", "0buyguide": "{username}{op_name} {num}个{unit}{role_name}", ... ``` 特别说明的,下面结构为全局替换。 ``` "replace":{ "?":"问号", "?":"问号" } ``` 在`main/config/config_K_v.json`中可选使用的服务api ``` "TTS_服务器-help": "baidu:百度翻译合成 youdao:有道TTS", "TTS_服务器": "youdao", "TTS_服务器_youdaoId": "", "TTS_服务器_youdaoKey": "", ``` 支持baidu、[有道](https://ai.youdao.com/gw.s#/)、[讯飞](https://www.xfyun.cn/)。 使用有道则需要Id和Key。 ``` "TTS_服务器_youdaoId": "7xxxxxxxxxxxxxxa", "TTS_服务器_youdaoKey": "yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxP", ``` 使用讯飞则需要应用Id、Key、Secret。可设置发音人。 ``` "TTS_服务器_xfId": "6xxxxxxb", "TTS_服务器_xfKey": "4xxxxxxxx9", "TTS_服务器_xfSecret": "YxxxxxxxBh", "TTS_服务器_xfVoice-help": "讯飞发音人 xiaoyan:小燕甜美女声 aisjiuxu:许久亲切男声 aisxping:小萍知性女声 aisjinger:小婧亲切女声 aisbabyxu:许小宝可爱童声 random:随机", "TTS_服务器_xfVoice": "random", ``` #### 弹幕窗(在v0.20.4移除) 构建gtk需要gtk3,先行安装[gtk](https://www.gtk.org/) release 由于某些[原因](https://github.com/golang/go/issues/57328#issuecomment-1353413399),Linux默认不编译gtk界面 Windows默认不编译 ``` 编译命令 cd main go build -v -tags `gtk` -o main.exe -i main.go ``` #### 弹幕处理/响应 默认开启了 - 反射弹幕机 启动时加载,当弹幕内容与`main/config_auto_reply.json`中所设键名相同时,在登录的情况下,会自动发送对应值的弹幕 - 相同合并 当短时间存在大量完全相同的弹幕时,他们将合并显示。 - 更少弹幕 过滤掉自身重复度及最近弹幕重复度高的弹幕 - 更短弹幕 当与上条弹幕具有相同开头的开头时,重复的部分会用...替代 仅对显示效果进行处理,而不处理输出到日志。更多设置见`main/config/config_F.json` ### 运行 #### 方法 1. 预先编译 下载安装[golang](https://go.dev/)/[golangCN](https://golang.google.cn/) clone/下载本项目。进入`main`目录(文件夹),运行: ``` linux: CGO_ENABLED=0 go build . windows: set CGO_ENABLED=0;go build . ``` 再运行生成的`main.exe`或`main` 2. 即时编译 下载安装[golang](https://go.dev/)/[golangCN](https://golang.google.cn/) clone/下载本项目。进入`main`目录(文件夹),运行: ``` linux: CGO_ENABLED=0 go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] windows: set CGO_ENABLED=0;go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] ``` 3. docker部署 经测试可以部署到`debian`镜像上,注意首先得[更新ca](https://stackoverflow.com/questions/64462922/docker-multi-stage-build-go-image-x509-certificate-signed-by-unknown-authorit) ``` apt-get update && apt-get install -y ca-certificates openssl ``` 如果你日常使用windows,但在debian运行,那还需先编译linux版本 下载安装[golang](https://go.dev/)/[golangCN](https://golang.google.cn/) clone/下载本项目。进入`main`目录(文件夹),运行: ``` set GOOS=linux set CGO_ENABLED=0 go build . ``` 注意实际使用时,在`config_K_v.json`关闭`tts`等需要关闭界面及音频的功能,配置好录播存放位置,做好直播流服务的端口映射 4. github编译 前往[releases](https://github.com/qydysky/bili_danmu/releases)页下载对应系统版本。解压后进入`main`目录(文件夹),运行`main`(`main.exe`)。 ``` ./main [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] ./main.exe [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] ``` #### 注意事项 * 其中[]内的内容为可选项 * 当`-r`,`-ckv`为空时,将尝试从环境变量中获取,分别对应键值`r`,`ckv`(>v0.14.21) * 法1,2,3建议使用最新提交 * 程序受主机时区配置影响,注意正确配置主机时区 * 弹幕及礼物默认会记录于danmu.log中 * 部分功能(如签到、发送弹幕、获取原画等)**需要在`cookie路径`下对应位置放置有效`cookie.txt`才可用** 或 **运行时按提示使用扫码登录成功后才可用(登录信息会保存在`cookie路径`中)**(`cookie路径`(>v0.14.26)默认为程序目录下的`cookie.txt`) * 在golang1.20+,由于某些[原因](https://github.com/golang/go/issues/57328#issuecomment-1353413399),你可能需要在构建时添加`CGO_ENABLED=0` * 由于通常是发现功能不正常时,才会检查b站是否更新,又因日常录播并不会使用到全部功能,所以并不能确保全部功能都能正常运行 * 离线编译:release版本将包含`vendor`压缩文件(>v0.15.7)。下载源代码及vendor压缩文件,解压后将`vendor`文件夹放置在`go.mod`同级目录时,你可以在`main`文件夹使用`go build -mod=vendor -v .`进行离线构建 源代码链接: `https://github.com/qydysky/bili_danmu/archive/refs/tags/{version}.zip` vendor链接: `https://github.com/qydysky/bili_danmu/releases/download/{version}/vendor.zip` * 组件优化:从源代码编译时,可以将各文件中存在的import项注释(存在`//`注释的),对应的组件将不会编译。这会使对应功能缺失,但能有效减少产物大小。 例如: 注释所有`//removable`后,在main目录下,使用下述命令编译时,产物将由17.9M->10M(v0.20.3时) ``` CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -buildvcs=false -v -buildmode=exe . ``` #### 关于更新版本v0.{y}.{z} * 当bilibili停止服务时,将会发布v1版本。 * 当发生**不兼容**的改动(删减原来有效、修改有效项的含义)时,将会发布v0.{y+1}.0版。更新前,你需要关注更新说明,以确认变动的配置项的影响。 * 当发生**向下兼容**的改动(修复、新增功能)时,将会发布v0.{y}.{z+1}版。通常只需要覆盖主体`main`(`main.exe`)即可更新。 * 另外`releases`页面中,`Pre-release`表示此版本为尚未经过验证的版本,或存在重大bug,`Latest`表示此版本经过验证,不存在明显的重大bug。 ### 效果展示 以下内容可能过时,以实际运行为准 #### 命令窗口(以下为截取) ``` //启动 qydysky@DESKTOP-5CV1EFA:~/程序/git/go/src/github.com/qydysky/bili_danmu/main$ go run main.go -r 21320551 I: 2021/02/18 20:33:09 api 小心心加密 [如需加密,会自动打开 http://127.0.0.1:33673] I: 2021/02/18 20:33:09 api 小心心加密 [启动] PID:14544 房间号: 21320551 T: 2021/02/18 20:33:09 api 新建 [ok] T: 2021/02/18 20:33:09 api 获取房号 [获取房号] T: 2021/02/18 20:33:10 api LIVE_BUVID [获取LIVE_BUVID] I: 2021/02/18 20:33:10 api LIVE_BUVID [存在] T: 2021/02/18 20:33:11 api 获取Token [ok] I: 2021/02/18 20:33:13 api 获取直播流 [轮播中] T: 2021/02/18 20:33:13 api 银瓜子=>硬币 [银瓜子=>硬币] I: 2021/02/18 20:33:15 api 银瓜子=>硬币 [现在有银瓜子 540 个] W: 2021/02/18 20:33:15 api 银瓜子=>硬币 [当前银瓜子数量不足] T: 2021/02/18 20:33:15 api 签到 [签到] I: 2021/02/18 20:33:19 api 获取客户版本 [api version 2.6.25] I: 2021/02/18 20:33:21 api 获取热门榜 [热门榜: 虚拟主播 50+] I: 2021/02/18 20:33:23 bilidanmu Demo [连接到房间 21320551] I: 2021/02/18 20:33:23 bilidanmu Demo [连接 wss://tx-bj-live-comet-02.chat.bilibili.com/sub] T: 2021/02/18 20:33:23 api 小心心 [获取小心心] I: 2021/02/18 20:33:23 bilidanmu Demo [已连接到房间 乙女音Official ( 21320551 )] I: 2021/02/18 20:33:23 bilidanmu Demo [【b限】学《巴啦啦小魔仙》] I: 2021/02/18 20:33:24 bilidanmu Demo [获取人气] T: 2021/02/18 20:33:25 api 礼物列表 [获取礼物列表] I: 2021/02/18 20:33:27 api 获取舰长数 [舰长数获取成功 471] I: 2021/02/18 20:33:27 弹幕发送 [发送 至 21320551] I: 2021/02/18 20:33:27 功能 [营收 ¥0.00] I: 2021/02/18 20:33:29 api 礼物列表 [成功] I: 2021/02/18 20:33:29 api 小心心 [今天小心心已满!] ``` ``` //普通弹幕 老鸡捉小鹰 你快扒拉他 你这好像是补刀 吓人 ``` ``` //大航海 >>> 欢迎舰长 Mana_单推... 进入直播间 ``` ``` //礼物 ==== 超级角击 投喂 1 个 摩天轮 ==== ``` ``` //同字符串合并 7 x 原神公测B服冲冲冲 ``` ``` //同字符忽略 原神公测B站冲冲冲 ...B服冲冲冲 ``` ``` //SC ==== SC: 凪穗 有了OTO能量,我们才能够坚强,prprpr OTOエネルギーがあれば、私たちは強くなれる。prprprpr ==== ``` ``` //其他会出现在命令行的信息 //热门榜 I: 2021/02/18 14:59:00 Msg 房 [热门榜 虚拟 4] //人气 I: 2021/02/18 14:58:51 Reply 人气 [当前人气 450869] //营收 I: 2021/02/18 14:58:24 功能 [营收 ¥247.80] //语音 I: 2021/02/18 14:59:00 TTS [0superchat SC: 三得笠·阿克曼茶 8888888 天才oto天才 ] ``` ctrl+c退出,会同时追加记录到文件danmu.log中(文件记录完整信息,不会减少附加功能作用的弹幕) #### danmu.log 基本同命令行显示,不同下列: ``` //弹幕 上述合并、忽略都不会起作用 I: 2021/02/18 07:24:55 Msg [从天上掉下来的骚年 : 秀才] //礼物 超过设定限额的将会在命令行中显示,级别为I T: 2021/02/18 07:30:30 Msg 礼 [正道的光博航同志 投喂 1 个 上上签 ¥1.0] I: 2021/02/18 14:52:31 Msg 礼 [三千千千千千千 投喂 1 个 爱之魔力 ¥28.0] //sc I: 2021/02/18 14:40:54 Msg 礼 [SC: 加拉入我心 ¥ 30 关注了乙女音,我才能够得到快乐 乙女音符に注目してこそ、私は幸せになれるのです。] I: 2021/02/18 21:48:49 Msg 房 [欢迎舰长 Mana_单推... 进入直播间] ``` #### Gtk弹幕窗(Linux Only)(在v0.20.4移除)   更多内容详见注释,如有疑问请发issues,欢迎pr