Under the Red storage tier, MP4 finalization (TS->MP4 remux) was being skipped, so tasks never reached Completed and the segment_completed event script — which uploads the file and deletes the local source to free space — never ran. The disk could never recover, deadlocking all recording and transcoding. Two reversed checks caused this: (1) FfmpegService gated finalization on the legacy HasEnoughSpace MB threshold (effectively 4GB) instead of the tier system, and (2) the polling loop only resumed paused finalizations when NOT in the Red tier. Now finalization is gated solely on ShouldPauseActive (true Red only) and the polling loop always attempts to resume it every cycle, since finalization is the very mechanism that frees space. Once any segment finalizes, the upload+delete script runs and the disk recovers, letting the rest finish. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| docs | ||
| frontend | ||
| mobile | ||
| scripts | ||
| src | ||
| tests/LiveRecorder.Tests | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Jenkinsfile | ||
| LiveRecorder.sln | ||
| README.md | ||
Live Recorder
Live Recorder 是一个多平台直播录制系统,支持自动检测开播、实时录制、弹幕采集、通知推送与事件脚本编排。
- 后端:
.NET 8 Web API + EF Core + SQLite - 前端:
Vue 3 + TypeScript + Element Plus
当前已适配 抖音(Douyin)与 Bilibili(部分),架构将平台特有逻辑隔离在 Platforms 目录下,新增虎牙、斗鱼、快手等平台无需改动应用层服务。
目录结构
.
├─ src
│ ├─ LiveRecorder.Domain # 实体与枚举
│ ├─ LiveRecorder.Application # 接口、DTO、应用服务
│ ├─ LiveRecorder.Infrastructure # 持久层、平台适配器、后台服务
│ └─ LiveRecorder.WebApi # REST API 与中间件
├─ frontend # Vue 3 SPA
│ └─ src
│ ├─ api / components / composables / router / stores / styles / views
├─ docker-compose.yml
├─ Jenkinsfile
└─ README.md
核心功能
直播录制
- 支持分享链接与短链解析,自动提取真实房间号
- 后台轮询检测直播状态,可配置轮询间隔与自动录制开关
- 支持
MP4(单文件)与TS(分段)两种输出格式 - 内置三种录制模板:
StreamCopy、BalancedMp4、ArchiveTs - 断线重连:可配置重连开关、最大重连延迟、读写超时
- 存储守护:启动前检查磁盘剩余空间,不足时拒绝录制
弹幕采集
弹幕通过 WebSocket 实时连接各平台的弹幕服务器,以 XML 格式分段写入文件。
- 抖音弹幕:通过
webcast/im/fetch/获取连接信息,建立 WSS 长连接,使用a_bogus签名算法(基于dycast开源项目的abogus.js),支持 Protobuf 解码 - Bilibili 弹幕:通过 Bilibili 直播 WebSocket 协议连接弹幕服务器,支持聊天、进入、关注、礼物等事件
- 弹幕事件类型:聊天(chat)、礼物(gift)、点赞(like)、进入(enter)、关注(member)等
- 弹幕录制可按设置只保留聊天弹幕或包含所有事件类型
- 弹幕文件与视频文件同目录、同名(
.xml扩展名),内部以结构化 XML 保存
通知推送
- 邮件通知:支持 SMTP 配置、SSL、自定义发件人与 HTML 模板
- 开播提醒:直播间上线时发送
- 异常提醒:录制异常时发送
- 模板变量:
{{appName}}、{{anchor}}、{{title}}、{{summary}}、{{detail}}等
- Webhook 通知:支持自定义 URL、请求头、超时配置
- 开播事件与异常事件分别可独立开关
- 支持测试发送验证连通性
- 负载包含直播间信息、录制任务信息等完整上下文
事件脚本
支持在关键生命周期节点执行自定义脚本(Shell / PowerShell 内联或外部脚本文件):
| 事件 | 说明 |
|---|---|
live_started |
检测到直播上线时触发 |
live_ended |
检测到直播下线时触发 |
segment_completed |
一个录制分片完成时触发 |
脚本通过环境变量获取上下文信息:
LIVE_RECORDER_EVENT # 事件类型
LIVE_RECORDER_PLATFORM # 平台名称
LIVE_RECORDER_LIVE_ROOM_ID # 直播间内部 ID
LIVE_RECORDER_ROOM_ID # 平台房间号
LIVE_RECORDER_TITLE # 直播间标题
LIVE_RECORDER_ANCHOR # 主播昵称
LIVE_RECORDER_SOURCE_URL # 源 URL
LIVE_RECORDER_OCCURRED_AT_UTC # 事件发生时间(北京时间)
LIVE_RECORDER_SEGMENT_FILE_PATH # 分片文件路径(仅 segment_completed)
LIVE_RECORDER_DANMAKU_FILE_PATH # 弹幕文件路径(仅 segment_completed)
LIVE_RECORDER_DURATION_SECONDS # 分片时长(仅 segment_completed)
支持超时控制与自定义日志输出。
异常恢复(Recovery)
- 自动检测处于 Live 状态但未在录制的直播间
- 自动检测录制完成但未做最终化(MP4 remux)的任务
- 支持一键重试录制或逐一恢复
- 后台轮询调度器同时兼具恢复层功能:当 ffmpeg 异常退出而直播间仍在直播时自动重新创建录制任务
数据保留清理(Retention)
- 可配置保留天数,超期自动清理录制记录、弹幕文件、视频文件与系统日志
- 支持后台定时清理(每 24 小时执行一次)
每日回顾(Daily Review)
- 按日期查看当天所有录制会话的汇总信息
- 亮点卡片:最长录制、最多弹幕、最多异常等
- 时间线视图展示会话与分片时间段
- 弹幕数量随时间分布的可视化数据
系统日志
- 持久化系统日志,支持按类别、时间筛选
- 日志关联直播间、录制会话、录制任务
- 可在前端日志页面实时查看
前端界面
- 登录页
- 直播间管理(添加、编辑、删除、状态查看、快速录制)
- 录制任务列表与详情
- 录制会话列表与详情
- 日志查看器
- 每日回顾
- 异常恢复页面
- 系统设置(录制、通知、弹幕、事件脚本、保留策略、平台配置)
- 路由懒加载,Vite vendor chunk 拆分
适配器架构
平台适配器接口
ILivePlatformAdapter
├─ ParseRoomAsync(input) # 解析分享链接、提取房间 ID
├─ GetLiveStatusAsync(roomId) # 获取直播状态、标题、主播名、封面
└─ GetStreamUrlAsync(roomId) # 获取推流地址
ILiveDanmakuAdapter
├─ CanHandle(platformType) # 判断是否支持该平台
└─ ConnectAsync(context) # 建立弹幕 WebSocket 连接
ILiveDanmakuConnection
└─ StartAsync(onEvent) # 开始接收弹幕,通过回调推送事件
抖音适配器
DouyinHttpClient:封装 User-Agent、Referer、Cookie、ttwid 管理- 分享链接解析、重定向跟随
- 从 HTML 中提取
roomId、user_unique_id、主播名、标题(支持新版__pace_f数据结构) - 调用
webcast/room/web/enter/获取直播间元信息 - 调用
webcast/im/fetch/获取弹幕 WebSocket 连接参数 a_bogus签名:通过 Node.js 子进程调用abogus.js计算请求签名
DouyinLivePlatformAdapter:解析推流地址,选择画质DouyinDanmakuAdapter:WebSocket 弹幕连接管理、心跳保活、自动重连
Bilibili 适配器
BilibiliHttpClient:Wbi 签名、分享链接解析BilibiliLivePlatformAdapter:直播状态查询,推流地址获取BilibiliDanmakuAdapter:弹幕 WebSocket 协议解析
设置项速览
录制设置
| 设置 | 说明 |
|---|---|
| FFmpeg 路径 | ffmpeg 可执行文件路径 |
| 输出根目录 | 录制文件输出根目录 |
| 输出模板 | 路径模板,支持 {platform} {roomId} {anchor} {title} {yyyy} {MM} {dd} {HHmmss} 等变量 |
| 默认画质 | 优先选择的流画质 |
| 保存格式 | MP4 / TS |
| 保存模式 | 单文件 / 分段 |
| 分段时长 | 分段模式下的每段时长(秒) |
| 录制模板 | StreamCopy / BalancedMp4 / ArchiveTs |
| 重连开关 | 断线后是否自动重连 |
| 最大重连延迟 | 重连退避最大秒数 |
| 读写超时 | 网络读写超时秒数 |
| 存储守护 | 启用磁盘空间检查 |
| 最低剩余空间 | 存储守护的最低空间阈值(GB) |
弹幕设置
| 设置 | 说明 |
|---|---|
| 启用弹幕录制 | 录制时是否同时采集弹幕 |
| 包含非聊天事件 | 是否记录进入、关注、礼物等非聊天弹幕 |
| 最小轮询间隔 | 弹幕连接重试的最小间隔(毫秒) |
| 最大重试延迟 | 弹幕连接重试退避最大秒数 |
通知设置
| 设置 | 说明 |
|---|---|
| 启用邮件通知 | SMTP 邮件通知总开关 |
| SMTP 服务器 / 端口 / SSL / 账号 | 邮件服务器配置 |
| 开播提醒 / 异常提醒 | 分别控制是否发送 |
| HTML 模板 | 可自定义邮件 HTML 模板,支持变量占位 |
| 启用 Webhook | Webhook 推送总开关 |
| Webhook URL / 请求头 / 超时 | Webhook 配置 |
| 开播通知 / 异常通知 | 分别控制是否推送 |
事件脚本设置
| 设置 | 说明 |
|---|---|
| 启用事件脚本 | 总开关 |
| 开播脚本 / 下播脚本 / 分片完成脚本 | 分别控制与配置 |
| 脚本模式 | 内联脚本 / 外部文件 |
| 超时(秒) | 脚本执行超时限制 |
保留策略
| 设置 | 说明 |
|---|---|
| 启用保留清理 | 是否开启自动清理 |
| 保留天数 | 超过此天数的记录将被清理 |
| 同时删除文件 | 是否删除对应的视频与弹幕文件 |
运行
后端
dotnet restore LiveRecorder.sln
dotnet build LiveRecorder.sln --no-restore -m:1
dotnet run --project src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj --urls http://localhost:5000
默认账号:
- 用户名:
admin - 密码:
Admin@123
Swagger:
前端
cd frontend
npm install
npm run dev
前端开发服务器:
Docker 部署
docker compose up -d
- API 服务运行在容器内
:8080 - Nginx 反向代理将
/api转发到 API,其余请求由前端 SPA 处理 - 默认暴露端口
HTTP_PORT(默认 8080) - 数据目录
./data与录制目录./records映射到宿主机 - 支持多架构构建(
linux/amd64,linux/arm64)
验证
dotnet build LiveRecorder.sln --no-restore -m:1npm run build(frontend 目录)- Docker Compose 完整部署验证通过
后续规划
- 完善 Bilibili 全功能适配,新增虎牙、斗鱼、快手适配器
- 按直播间独立配置录制参数
- 日志全文搜索与时间范围过滤
- 基于 JWT 或外部 SSO 替换轻量 Token 会话
- 弹幕回放播放器集成
- 录制文件自动上传至 S3/OSS 等对象存储