9.6 KiB
9.6 KiB
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 等对象存储