喜欢的直播总要蹲点?用 bililive-go 在 NAS 后台自动录制直播并远程管理,再用 cpolar 让外地也能看回放
喜欢的直播,十有八九不会在你清醒的时候开。
我追的几位主播经常凌晨一两点才开播,第二天早上醒来只剩一条"直播已结束"的灰字,想看回放还得等官方剪,剪完还未必留。蹲点蹲了两次我就放弃了------人不能为了看一场直播把作息拧成麻花。
但转念一想,这事其实不该靠人守。开播检测、拉流、落盘、切分段、结束收尾,全是机器擅长的活儿。真正缺的只是一个能常驻后台、开播自动录、还不占我多少硬盘的小工具。
这篇文章要做的,就是把这件事彻底交代清楚:在 NAS 或任意一台常开的机器上跑起 bililive-go,让它盯着几个直播间,开播就自动录;人不在家的时候,再用 cpolar 临时开一条入口,把录制列表和已录回放短时看一遍。
先说清楚这篇的边界,免得你按图施工时踩空。凡是本机真跑过、有输出可以贴的,我会明确写"实测";凡是需要 cpolar 账号和另一台异地设备才能验证的,我会老实标成规划阶段,不假装跑通过。写自托管教程最容易犯的错,就是把"文档里这么写的"当成"我这儿跑通了",这篇不干这事。
1 为什么是 bililive-go,而不是一堆脚本拼起来
先说选型,因为这决定了后面所有步骤。
自己撸一台录制机,无非是:定时轮询直播间状态 → 判断是否在播 → 调 FFmpeg 拉流 → 命名文件 → 切割。听起来不难,但每个环节都有坑:B 站接口会限流、直播间等级/清晰度要带 Cookie、flv 文件不修会有头损坏、播到一半换了房间名文件要对得上、录到半夜得知道什么时候停。
bililive-go 就是把这些坑一次性包圆的开源项目。它的 GitHub 仓库是 bililive-go/bililive-go,GPL-3.0 协议,当前 star 数 5752,最近一次推送是 2026-09-24(实测数据)。
我选它主要看三点:
- 它是单二进制。官方直接发编译好的可执行文件,macOS arm64 版本解压出来就是一个约 43MB 的二进制,不需要 Docker,不需要拉大镜像。
- 它自带 Web 管理台和 RPC。录制列表、开始/停止、已录文件都在网页里看,不用天天翻终端。
- 它支持多平台。B站、斗鱼、虎牙、抖音、YouTube、Twitch 等都在支持列表里,房间写 URL 就行。
第一点对我特别关键。我这台测试机的共享 Docker 环境磁盘本来就紧张,可用空间只剩 51Gi,再拉一个几百 MB 的镜像加数据卷,心里不舒服。单二进制方案把这块开销直接省掉了。
这篇里 bililive-go 负责的是"拉流录制 + 本地管理台"这一层;NAS 或常开机负责"7×24 常驻";cpolar 负责在最需要的那一小段时间里,把本机管理入口开给外地设备。三者职责分得很清楚。
先把这篇要达成的结果摆在这儿,后面每一步都朝它走:
- 下载 bililive-go 官方 v0.8.2 二进制,跑起来,确认版本和平台信息。
- 写
config.yml把直播间加进去,通过 RPC 接口确认房间被正确解析。 - 让它在后台常驻,开播自动录、录完整理成文件。
- 需要异地查看时,用 cpolar 临时开一条入口------这一条本文标注为规划阶段。
- 演示结束就关隧道,并对管理接口做基本的安全收尾。
text
你(外地)
|
| HTTPS
v
cpolar 临时入口
|
v
NAS / 常开主机
127.0.0.1:18081 <- bililive-go RPC + 管理台
|
| 轮询开播状态
v
直播平台(B站等)
|
| FFmpeg 拉流
v
录制输出目录(本地硬盘)


2 环境准备:确认你能跑单二进制
正式动手前把三个前提确认掉,能省掉后面一半的排错时间。
2.1 确认系统架构
bililive-go 官方给每个架构都发了对应的包,下错架构的解压出来跑不了。先在终端看自己是什么架构:
bash
uname -s -m
我这台实测输出是:
text
Darwin arm64
说明这是一台 Apple Silicon 的 macOS,对应要下 darwin-arm64 的包。如果你看到的是 Linux x86_64,那就下 linux-amd64;Linux aarch64 就下 linux-arm64。这一步别猜,直接看命令输出。
2.2 确认 FFmpeg 在位
bililive-go 自己不做转码和封装,拉流落盘的活儿交给 FFmpeg。所以 FFmpeg 必须在,而且要能在 PATH 里找到。
bash
which ffmpeg && ffmpeg -version | head -n 1
实测输出(macOS + Homebrew 环境):
text
/opt/homebrew/bin/ffmpeg
ffmpeg version 8.1.1 Copyright (c) 2000-2026 the FFmpeg developers
没装的话,macOS 用 brew install ffmpeg,Ubuntu/Debian 用 sudo apt install ffmpeg。这里提醒一句:FFmpeg 装完一定要用 which ffmpeg 再确认一遍,很多人是装了但 PATH 没生效,等下录制一直不落盘,回头查半天才发现是这个问题。
需要说明的是,bililive-go 自带的"自动下载 FFmpeg"功能目前只覆盖 Linux 和 Windows 平台,macOS 不在它的下载映射表里。实测日志里能直接看到这两行:
text
no download URL for darwin/arm64 in ffmpeg@n8.1-latest
所以 macOS 用户必须自己准备好 FFmpeg ,不要指望它自动帮你下。这不是报错,是平台覆盖范围的问题,日志之后紧跟着的 FFmpeg found in system PATH 才是真正生效的信号。
2.3 找一个长期开机的位置
录制服务要 7×24 盯着直播间,所以它得跑在一台常开的机器上------NAS、软路由、小主机、挂机的 Mac mini 都行。
如果你打算把录制目录放在 NAS 的共享盘上,建议先本机跑通,再把输出路径改到网络盘。顺序不能反。网络盘一旦挂载不稳定,你会分不清是录制服务的问题还是存储的问题,排错成本直接翻倍。

说明:本文配图中的终端、日志与配置界面均为中性示意图(占位主机名、示例 IP、示例房间号),不包含本机真实信息。
3 下载并跑起 bililive-go
3.1 拿到官方 v0.8.2 二进制
开源项目不要从第三方站下,直接去官方 Release。v0.8.2 的发布页是:
text
https://github.com/bililive-go/bililive-go/releases/tag/v0.8.2
官方在 v0.8.2 这个 tag 下发的 macOS arm64 包叫 bililive-darwin-arm64.tar.gz,实测大小 14560191 字节(约 14.5MB)。下载解压一条命令搞定:
bash
mkdir -p ~/bililive && cd ~/bililive
curl -L -o bililive-darwin-arm64.tar.gz \
https://github.com/bililive-go/bililive-go/releases/download/v0.8.2/bililive-darwin-arm64.tar.gz
tar -xzf bililive-darwin-arm64.tar.gz
ls -lh
解压后你会得到一个没有扩展名的可执行文件。实测这个二进制大小约 43MB,先给它执行权限,再看版本:
bash
chmod +x bililive-darwin-arm64
./bililive-darwin-arm64 --version
实测输出:
text
v0.8.2
版本号对上了,说明包没问题。这一步是后续所有验证的基准,版本不对就别往下走。

3.2 目录结构与配置约定
先看一眼它默认往哪写数据,免得到处找不到文件。默认情况它有这几个位置:
config.yml:主配置,写直播间、录制参数、通知等。用-c参数指定路径。.appdata/:应用数据目录,这里是app_data_path的默认值。lives.db:直播间与录制状态数据库。iostats.db:IO 与内存统计数据库。./:默认输出目录,由out_put_path控制。
实测启动日志里能看到数据库迁移完成的记录:
text
database migration completed (lives.db -> v3, iostats.db -> v2)
看到这两行说明 SQLite 持久化是好的,重启后录制状态不会丢。
3.3 用 RPC 模式启动服务
bililive-go 平时跑在后台,我们通过 RPC 接口和它打交道。启动时开启 RPC,并把监听地址按需要设置:
bash
./bililive-darwin-arm64 \
--enable-rpc \
--rpc-bind 127.0.0.1:18081 \
-c config.yml
这里有两个要点。
要点一:默认只监听本机。 我把 --rpc-bind 显式写成 127.0.0.1:18081,就是让它只在环回地址上开服务。这是有意为之的------管理接口一旦裸奔在 0.0.0.0,同网段任何设备都能打开你的录制面板。除非你明确知道自己在做什么,否则监听地址就写 127.0.0.1。
要点二:端口别撞车。 18081 是我选的,你可以按自己机器的情况改。如果启动时提示端口被占用,换个数字就行。另外后面 cpolar 只映射一个本地端口,记清楚你这里写的是哪个,映射时要用同一个。
启动成功的话,日志里会出现这一行:
text
Server start at 127.0.0.1:18081
实测启动日志里还能看到这些组件的就绪信息,说明它是个功能比较完整的服务:
text
bililive-scheduler tool is ready to use, version: v0.1.0
bililive-recorder tool is ready to use, version: v2.17.3
FFmpeg found in system PATH
Created 1 live rooms (1 listening, 0 not listening)

4 验证服务:先确认接口是活的
服务跑起来不代表能用。这一步不清空,后面录不下来全是瞎猜。
4.1 看版本与平台信息
打开另一个终端,请求 /api/info:
bash
curl -s http://127.0.0.1:18081/api/info | python3 -m json.tool
实测返回(节选关键字段):
json
{
"app_name": "BiliLive-go",
"app_version": "v0.8.2",
"platform": "darwin/arm64",
"go_version": "go1.25.14",
"is_launcher_managed": false
}
三个字段对上就说明服务是好的:app_name 是 BiliLive-go,app_version 是 v0.8.2,platform 是 darwin/arm64。如果 platform 和你 uname -m 的结果不一致,多半是下错了包,回 3.1 重新下。
4.2 看直播间解析结果
这一步是全文最关键的验证点。先往 config.yml 的 live_rooms 里加一个真实直播间。以 B 站为例,直播间地址形如 https://live.bilibili.com/22603245,写进配置:
yaml
live_rooms:
- url: https://live.bilibili.com/22603245
is_listening: true
保存后重启服务,或者通过管理台重载配置。然后请求 /api/lives:
bash
curl -s http://127.0.0.1:18081/api/lives | python3 -m json.tool
实测返回(关键字段):
json
[
{
"id": "deb127e76d6e14c16d7a3191850e5969",
"live_url": "https://live.bilibili.com/22603245",
"platform_cn_name": "哔哩哔哩",
"host_name": "永雏塔菲",
"room_name": "1个聋子1个瞎子1个哑巴",
"listening": true,
"recording": false,
"last_error": "response code 412 from user api"
}
]
能读到这些字段,就说明配置链路彻底打通了:房间 id 解析出来了、平台识别成 哔哩哔哩、主播名和房间名都拿到了、listening 是 true,也就是它已经在盯着这个房间。
这里必须解释一下 last_error。 实测返回里带着 response code 412 from user api,启动日志里也有对应的一行:
text
初始化直播间信息失败,将继续重试 error="response code 412 from user api" host=live.bilibili.com room=/22603245
412 是 B 站对未携带 cookies 的请求 的限流响应,不是程序报错,也不是配置写错了。它不影响 listening=true 这个状态------服务照样在轮询开播状态。但如果你想让录制更稳、拿更高清晰度、躲开这个限流,就得在配置里补上自己的 cookies。这是 B 站场景绕不开的一步。

5 把直播间管起来:录制与产物
接口通了,接下来是让它真正干活。
5.1 录制参数在哪配
config.yml 里和录制直接相关的几项:
yaml
interval: 60 # 轮询开播状态的间隔(秒)
out_put_path: ./ # 录制输出目录
ffmpeg_path: "" # 留空表示用 PATH 里的 ffmpeg
video_split_strategies:
on_room_name_changed: false # 房间改名是否另起一个文件
max_duration: 0 # 单文件最大时长(分钟),0 表示不按时间切
max_file_size: "0" # 单文件最大体积,0 表示不按体积切
几个参数的实际影响,展开说:
interval决定"开播后多久被录到"。设 60 秒就是以一分钟为粒度轮询,开播后最多一分钟内开始拉流。想更快可以调小,但请求频率高了对平台也不友好,60 秒是个平衡点。max_duration和max_file_size都设 0 就是不切分。一场直播三四个小时的话,单文件会很大,后期想找某一段很痛苦。建议至少设一个 ,比如max_duration: 120,两小时切一段,方便定位也方便传。on_room_name_changed打开后,主播一改名就另起文件。有些主播喜欢在直播中间换标题,打开这项文件会变碎,关掉则更整齐。
这些值没有标准答案,看你怎么用。只是别全留默认就完事------尤其是切分策略,留 0 的话第一次录到超长直播,你会后悔的。
5.2 录制完之后的事
录完一个文件,还有几个可选项,都在 on_record_finished 下面:
yaml
on_record_finished:
convert_to_mp4: false # 是否转成 mp4
delete_flv_after_convert: false
fix_flv_at_first: true # 修正 flv 头部,建议保持 true
save_cover: false # 是否保存封面
fix_flv_at_first 默认就是 true,这项别关。B 站拉下来的 flv 经常头部不完整,不修的话播放器拖进度条会出问题,修一下能省很多"这文件怎么播一半"的困惑。
至于 convert_to_mp4,看你的播放场景。如果你只是自己电脑上看,flv 用 VLC 或 PotPlayer 都能放,不转也行,省一次转码时间;如果要丢给手机、电视、或者别的播放器,转成 mp4 兼容性明显更好。转码是 CPU 密集操作,NAS 性能一般的话,建议先不转,等有空再批量处理。
5.3 让它常驻后台
跑了就断、关了终端就停,那就不叫后台录制了。要让它在后台常驻,有两个思路。
思路一:用 nohup 挂后台。 简单直接:
bash
nohup ./bililive-darwin-arm64 \
--enable-rpc \
--rpc-bind 127.0.0.1:18081 \
-c config.yml \
> bililive-run.log 2>&1 &
日志会写进 bililive-run.log,随时 tail -f 看。适合先试跑几天。
思路二:做成系统服务。 macOS 用 launchd,Linux/NAS 用 systemd,好处是开机自启、崩溃自动重启。配置文件的写法各系统不同,建议直接照官方文档对应平台的说明来写,不要凭感觉套。
我这里给的是 macOS 上用 launchd 的最小骨架,路径按你自己机器的实际情况改:
bash
# 创建 plist(路径中的用户名改成你自己的)
cat > ~/Library/LaunchAgents/com.bililive.go.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.bililive.go</string>
<key>ProgramArguments</key>
<array>
<string>/Users/你的用户名/bililive/bililive-darwin-arm64</string>
<string>--enable-rpc</string>
<string>--rpc-bind</string>
<string>127.0.0.1:18081</string>
<string>-c</string>
<string>/Users/你的用户名/bililive/config.yml</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/你的用户名/bililive</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
EOF
# 加载并启动
launchctl load ~/Library/LaunchAgents/com.bililive.go.plist
launchctl list | grep bililive
KeepAlive 设成 true,进程意外退出会被自动拉起,这对"长时间无人值守录制"很重要。加载完用 launchctl list | grep bililive 确认能看到条目。

6 从外地看:用 cpolar 把管理入口短时开出来
到这里,录制这块已经在家里跑起来了。但问题还在:人在外地的时候,我想看一眼"昨晚那个直播间录到没有""录下来的文件多大",怎么办?
管理台在 127.0.0.1:18081,只有本机能访问。这时候 cpolar 就派上用场了------它是内网穿透工具,能把本机的一个端口映射成公网地址,让外地的设备也能访问。
先把边界说清楚:本节的隧道建立属于规划阶段。建隧道需要 cpolar 账号的 authtoken,我这台测试机没有账号,因此下面的流程是完整的、可照做的步骤说明,但我没有建立真实公网隧道,也没有用第二台异地设备做验收。这一点必须如实交代。
6.1 安装 cpolar(以 macOS 为例)
cpolar 支持多平台,macOS 走 Homebrew:
bash
brew tap probezy/core && brew install cpolar
sudo cpolar service install
sudo cpolar service start
官方 macOS 安装说明在 https://www.cpolar.com/blog/macos-installation-cpolar,快速入门在 https://www.cpolar.com/blog/cpolar-quick-start-tutorial-macos-series,装的时候对着看。
如果你是在群晖 NAS 上跑 bililive-go,cpolar 走套件安装,别照搬上面的 Homebrew 命令:
- 套件下载页:
https://www.cpolar.com/synology-cpolar-suite - 群晖快速入门:
https://www.cpolar.com/blog/cpolar-quick-start-tutorial-synology-nas-series - 远程访问用法:
https://www.cpolar.com/blog/use-cpolar-to-access-synology-nas-remotely
群晖的安装路径是"套件中心 → 手动安装",装完打开 cpolar 套件,默认管理界面在 9200 端口,首次登录后会自动获取 authtoken 并写入配置文件。这里特别提醒:群晖自身的管理端口是 5000/5001,不要和 cpolar 的 9200 搞混。
其他平台(Linux 一键脚本、Windows、Docker、OpenWrt、树莓派)都有对应的安装文档,按自己环境选。
6.2 登录并确认服务状态
服务起没起,两个命令就能确认:
bash
cpolar version
curl -s http://127.0.0.1:9200 || echo "服务未启动"
第二条能返回内容,说明 cpolar 的本地 Web UI 是活的。cpolar 的 Web UI 默认端口就是 9200,地址是 http://127.0.0.1:9200/。
账号绑定有两条路,任选其一:
- Web UI 登录 :打开
http://127.0.0.1:9200,在界面里登录 cpolar 账号,登录成功后 token 会自动写入配置。 - 命令行写入 :在 cpolar 后台
https://dashboard.cpolar.com/找到自己的 authtoken,然后在本机执行cpolar authtoken 你的authtoken。
authtoken 是账号凭证,在后台复制粘贴即可。不要把 authtoken 贴到聊天群、截图或者公开的配置文件里,它等同于你账号的钥匙。
6.3 开一条指向管理端口的隧道
隧道类型选 HTTP,因为我们要开的是一个网页管理台,不是 SSH 或数据库。目标端口就是前面 bililive-go 的 RPC 端口:
bash
cpolar http 18081
执行后,cpolar 会输出这次的公网地址,形如 https://xxxx.r13.cpolar.cn。这条地址现在指向你本机的 18081,也就是 bililive-go 的管理台。
想连续开多条隧道又不想在前台反复敲命令,可以直接在 Web UI 的 状态 → 在线隧道列表 里看当前在线的隧道和对应的公网地址,管理起来更清楚。
如果你想让这个地址固定下来、不用每次都变,那就涉及保留二级子域名。免费套餐生成的公网地址是随机临时地址,24 小时内会变化 ;固定二级子域名需要基础套餐或以上。官方那篇 https://www.cpolar.com/blog/configure-the-secondary-subdomain-name 写得很清楚,按需选。
6.4 安全收尾:这步比开通更重要
管理台暴露到公网这个动作本身是有风险的,尤其 bililive-go 的 RPC 接口如果没有额外鉴权,谁能打开这个地址谁就能动你的录制任务。所以下面几条不是可选项:
- 只开必须的端口 。我们只映射了
18081一个管理端口,不要顺手把自己 NAS 的5000或者 SSH 的22一起开出去。 - 短时开放,用完即关。看完录制状态、下载完文件,回 Web UI 把隧道停掉。这条隧道不该 7×24 挂着。
- 给管理接口加一层限制。能配 token 就配 token,能用 cpolar 的 IP 白名单(对应更高套餐)就上白名单。
- 不要长期公网暴露录制主机。录制机往往还跑着别的服务,一台暴露出去,等于把整个内网的信誉暴露了。
坦白讲,最省事的做法是把"偶尔看回放"和"长期暴露服务"彻底分开:录制常年在内网跑,需要看的时候临时开一条隧道,看完关掉。风险窗口就只有你真正需要它的那几分钟。

7 常见问题排查
按"从里到外"的顺序排,不要一上来就怀疑 cpolar。
7.1 /api/lives 里 listening 是 false
先查 config.yml 里对应房间的 is_listening 是不是 true。这个字段写成了 false,服务就不会盯这个房间。改完记得重启服务或重载配置。
7.2 日志一直报 response code 412
这是 B 站对未带 cookies 请求的限流,前面 4.2 解释过。想要更稳的录制和更高清晰度,就在配置里补上 cookies。没有 cookies 时也能跑,只是别指望它一直顺。
7.3 开播了但没落盘
按这个顺序查:
which ffmpeg能不能返回路径。macOS 下它不会自动下载 FFmpeg,这一步是硬门槛。out_put_path指向的目录存不存在、有没有写权限。指向网络盘时尤要确认挂载正常。/api/info里的platform和本机架构是否一致。包下错了,进程能起来,但拉流会失败。
7.4 通过 cpolar 地址打开,页面打不开或空白
先在本机 访问 http://127.0.0.1:18081 确认服务本身是好的。本机能开、公网打不开,再查 cpolar:隧道是不是在线(状态 → 在线隧道列表)、目标端口有没有填成 bililive-go 的实际 RPC 端口。这两点最容易出错。
7.5 硬盘涨得太快
一场直播几小时,文件很大很正常。三个应对:把 max_duration 设成合理值分片;把 out_put_path 指到容量大的盘;定期清理------不需要的录播该删就删。录制服务不加清理策略,硬盘早晚被喂饱,这是长期跑必须提前想的。
8 总结
到这一步,你手上已经有了一套能自己盯着直播间的录制服务:单二进制跑在常开的机器上,直播间写进配置就自动开着播,录制状态和产物都能通过管理台看到,整个链路无论是 HTTP 接口还是本地落盘都已经打通。你不再需要为了追一场直播熬到凌晨,开播这件事交给机器守就行。
把关键步骤收个尾:
- 用
curl从官方 Release 下bililive-darwin-arm64.tar.gz(v0.8.2,约 14.5MB),解压得到约 43MB 的单二进制,--version确认输出版本号。 - 以
--enable-rpc --rpc-bind 127.0.0.1:18081 -c config.yml启动,用/api/info断言app_version=v0.8.2、platform=darwin/arm64,用/api/lives断言房间id、host_name、room_name解析正确且listening=true。 - 需要异地查看时用
cpolar http 18081临时开一条 HTTP 隧道,看完立刻关掉;管理接口别裸放公网。
后续要扩展,方向也很自然:把 cpolar 隧道换成固定的二级子域名,就不用每次重新记地址;给录制目录单独挂一块盘,录播涨起来也不挤占系统盘;再配上定时清理或外部通知(配置里已经预留了 Telegram、邮件、ntfy、Bark 等通知通道),录制就真成了"设好就不用管"的后台服务。这套思路之所以省事,是因为它把"录制"和"访问"这两件频率完全不同的事拆开了------录制常年在内网常驻,访问按需临时开,各自做各自擅长的事。
最后,把这篇里三个未实测、属于规划阶段的部分如实交代,免得你按图施工时踩空:
- cpolar 真实公网隧道:建立隧道需要 cpolar 账号的 authtoken,本文没有账号,因此只写了完整流程,没有建立真实隧道,这一环节属于规划阶段。
- 浏览器界面点击流验收:本机浏览器界面交互验收受策略限制,本文的验收口径是 HTTP 接口断言与启动日志,没有做管理台的 UI 点击验证。
- 长时间真实录制落盘:真实录制能否稳定落盘,取决于目标平台当时是否有直播、是否带 cookies(B 站会返回 412 限流)。本文验证到"直播间被正确解析且处于 listening 状态",没有做长时间真实录制。