将 README 改写为产品文档;移除微信/EasyTier/工作台等遗留模块;新增 youLIVE 目标端监控、摄像头推流、质量守卫与转播历史能力。 Co-authored-by: Cursor <cursoragent@cursor.com>
405 lines
17 KiB
Markdown
405 lines
17 KiB
Markdown
# 无人直播助手
|
||
|
||
Windows 桌面端 **抖音 → YouTube 无人转播** 控制台:内置 Electron 客户端、FastAPI 控制面(`web2`)、FFmpeg 推流 worker、多频道 Pro、推流诊断。
|
||
|
||
[](https://www.python.org/)
|
||
[](https://www.electronjs.org/)
|
||
[]()
|
||
|
||
> 录制核心基于 [DouyinLiveRecorder](https://github.com/ihmily/DouyinLiveRecorder) 生态;Linux 全功能服务端可参考同级项目 **sh2**(`d2ypp2`)。本仓库侧重 **Windows 懒人包 + Electron 控制台**。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [快速开始](#快速开始)
|
||
- [产品定位](#产品定位)
|
||
- [系统架构](#系统架构)
|
||
- [仓库结构](#仓库结构)
|
||
- [界面与功能](#界面与功能)
|
||
- [web2 API](#web2-api)
|
||
- [配置与数据路径](#配置与数据路径)
|
||
- [单频道与多频道 Pro](#单频道与多频道-pro)
|
||
- [推流诊断 / 质量守卫 / 转播历史](#推流诊断--质量守卫--转播历史)
|
||
- [youLIVE 目标端监控](#youlive-目标端监控)
|
||
- [摄像头直推](#摄像头直推)
|
||
- [会员登录门禁(可选)](#会员登录门禁可选)
|
||
- [开发与构建](#开发与构建)
|
||
- [打包发布](#打包发布)
|
||
- [环境变量](#环境变量)
|
||
- [故障排查](#故障排查)
|
||
- [相关文档](#相关文档)
|
||
- [许可证](#许可证)
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 最终用户(便携包)
|
||
|
||
1. 运行发布包中的 **无人直播助手** 可执行文件。
|
||
2. 打开 **直播** 页,在界面中填写:
|
||
- YouTube **串流密钥**(Studio → 直播 → 串流设置);
|
||
- **源站地址**(抖音直播间 URL,每行一个)。
|
||
3. 点击 **开始直播**;在 **当前直播日志** 中查看业务状态与 FFmpeg 输出。
|
||
|
||
### 开发者
|
||
|
||
```bash
|
||
cd electron
|
||
pnpm install
|
||
pnpm dev
|
||
```
|
||
|
||
首次开发若缺少离线 Python/FFmpeg,可在 `electron/` 下执行 `pnpm prepare:runtime`。
|
||
|
||
仅调试后端 API(仓库根目录):
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
uvicorn web2:app --host 127.0.0.1 --port 8001 --reload
|
||
```
|
||
|
||
---
|
||
|
||
## 产品定位
|
||
|
||
| 场景 | 说明 |
|
||
|------|------|
|
||
| **无人转播** | 从抖音等源站拉流,经本机 FFmpeg 推送到 YouTube RTMPS。 |
|
||
| **值守运行** | 通过内置 `BuiltinSupervisor`(或可选 PM2)管理 `youtube2.py`、`douyin_youtube_ffplay.py` 等 worker。 |
|
||
| **桌面控制台** | Electron 提供直播、网络、系统等页面。 |
|
||
| **多路 Pro** | 多组「一个抖音直播间 ↔ 一个 YouTube 串流密钥」并行,进程名 `youtube2__{channelId}`。 |
|
||
|
||
**配对原则(强制)**
|
||
|
||
- 一个抖音直播间地址只对应 **一个** YouTube 串流密钥;
|
||
- **禁止** 同一抖音向多个 YouTube 推流;
|
||
- **禁止** 多个抖音共用同一密钥。
|
||
|
||
---
|
||
|
||
## 系统架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Electron 渲染进程 (React + Vite) │
|
||
│ 直播 / 摄像头 / 网络 / 系统 │
|
||
└───────────────────────────┬─────────────────────────────────────┘
|
||
│ preload (contextBridge)
|
||
┌───────────────────────────▼─────────────────────────────────────┐
|
||
│ Electron 主进程 │
|
||
│ · 启动 uvicorn (web2:app) │
|
||
│ · sql.js → client-data.sqlite │
|
||
│ · 托盘、深链 --nav= │
|
||
│ · YouTube Studio 系统浏览器侧车 │
|
||
│ · youLIVE 服务(监听 / 弹幕 / 桌面通知 / 本地 SQLite) │
|
||
└───────────────────────────┬─────────────────────────────────────┘
|
||
│ http://127.0.0.1:8001(可 0.0.0.0)
|
||
┌───────────────────────────▼─────────────────────────────────────┐
|
||
│ web2.py (FastAPI) │
|
||
│ 进程启停 / 状态诊断 / 配置读写 / Pro / 质量守卫 / 会话历史 │
|
||
└───────────────────────────┬─────────────────────────────────────┘
|
||
│
|
||
┌───────────────────┼───────────────────┐
|
||
▼ ▼ ▼
|
||
youtube2.py douyin_youtube_ffplay.py tiktok*.py
|
||
│ │
|
||
└──────── FFmpeg + Supervisor / PM2 ────────────────┘
|
||
```
|
||
|
||
| 模块 | 文件 | 职责 |
|
||
|------|------|------|
|
||
| Worker | `youtube2.py`, `douyin_youtube_ffplay.py`, `main.py` | 拉流、转码、推流 |
|
||
| 控制面 | `web2.py` | HTTP API |
|
||
| 运行时诊断 | `web2_process_runtime.py` | `business_status`、FFmpeg 速度/帧数 |
|
||
| 质量守卫 | `web2_quality_guard.py` | 推流质量评分 |
|
||
| 转播历史 | `web2_relay_log.py` | 会话 SQLite、日志导入 |
|
||
| 配置治理 | `web2_config_governance.py` | 保存前备份、恢复 |
|
||
| 多频道 | `web2_relay_pro.py` | `youtube_channels.json`、`config/relay_pro/` |
|
||
| 摄像头 | `web2_camera.py`, `camera_youtube.py` | DirectShow 采集、NVENC 推流 |
|
||
| youLIVE | `electron/src/youlive/` | YouTube 监听、弹幕、账号、桌面通知 |
|
||
| 主进程 | `electron/src/main/` | 运行时打包、IPC、本地 DB |
|
||
| 界面 | `electron/src/renderer/` | React SPA |
|
||
|
||
---
|
||
|
||
## 仓库结构
|
||
|
||
```
|
||
.
|
||
├── electron/ # 无人直播助手(Electron + React)
|
||
│ ├── src/main/ # 主进程
|
||
│ ├── src/preload/ # contextBridge
|
||
│ ├── src/renderer/ # UI(直播 / 摄像头 / 网络 / 系统)
|
||
│ ├── src/youlive/ # 内嵌 youLIVE(主进程服务 + 共享类型)
|
||
│ └── scripts/ # 离线运行时、图标
|
||
├── web2.py # FastAPI 入口
|
||
├── web2_*.py # 后端子模块
|
||
├── config/ # 运行配置
|
||
├── backup_config/__web__/ # 配置自动备份
|
||
├── runtime/youtube_relay/ # 转播会话 sessions.sqlite
|
||
├── src/ # 录制核心(spider、stream、room…)
|
||
├── camera_youtube.py # 摄像头→YouTube worker
|
||
├── douyin_youtube_ffplay.py # 抖音→YouTube 转播
|
||
├── youtube2.py # YouTube worker
|
||
├── docs/ # 补充文档
|
||
└── requirements.txt
|
||
```
|
||
|
||
---
|
||
|
||
## 界面与功能
|
||
|
||
| 页面 | 说明 |
|
||
|------|------|
|
||
| **直播** | 单频道 / Pro:抖音源站转播、密钥、监听、启停、链路诊断、转播历史 |
|
||
| **摄像头** | 物理摄像头 + 麦克风 → FFmpeg → YouTube(`camera_youtube` 进程) |
|
||
| **网络** | 测速、代理 |
|
||
| **系统** | 负载、开机启动、路径、会员登录限制开关 |
|
||
|
||
直播页能力摘要:
|
||
|
||
- **自适应轮询**:推流中 ~0.8s,空闲 ~4s,后台标签 ~30s
|
||
- **链路诊断**:源站 / 推流 / 目标三层检查(`GET /youtube/diagnostics`)
|
||
- **YouTube 目标端监控**:监听地址写入 `youtube_channels.json`,与转播线路绑定
|
||
- **桌面通知**:推流未到达 YouTube、目标端下播、弹幕关键词(需 youLIVE 桌面通知开启)
|
||
- **转播历史**:PM2 状态自动记会话;支持从 PM2 日志导入
|
||
- **配置历史备份**:保存前自动备份,界面可恢复
|
||
- **YouTube Studio**:系统浏览器打开,便于核对密钥
|
||
- **源站预览**:解析抖音 URL 并尝试显示主播昵称
|
||
- **配对校验**:Pro 多线路保存时检测抖音地址 / YouTube 密钥跨频道重复,冲突时展示横幅并阻止启动
|
||
|
||
---
|
||
|
||
## web2 API
|
||
|
||
默认:`http://127.0.0.1:8001`(`WEB2_PORT` 可改)。
|
||
|
||
| 分类 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| 健康 | `GET /health` | 存活(无需鉴权) |
|
||
| 进程 | `GET /process_monitor` | 任务列表(含 Pro 频道) |
|
||
| 进程 | `GET /start` `/stop` `/restart` | 参数 `process=` |
|
||
| 状态 | `GET /status?process=` | 进程状态 + 业务诊断 + FFmpeg 指标 |
|
||
| 配置 | `GET/POST /youtube/ini_model` | 结构化 `youtube.ini` |
|
||
| 配置 | `GET/POST /get_url_config` `save_url_config` | `URL_config.ini` |
|
||
| 配置 | `GET /config/backups?file=` | 历史备份列表 |
|
||
| 配置 | `POST /config/restore` | 恢复(`file`, `backupId`) |
|
||
| Pro | `/relay_pro/*` | 多频道 CRUD、密钥、URL、YouTube 监听地址、live_status |
|
||
| 诊断 | `GET /youtube/diagnostics` | 源站 / FFmpeg / 目标三层诊断 |
|
||
| 诊断 | `GET /youtube/quality_guard` | 质量评分(诊断内部复用) |
|
||
| 摄像头 | `GET /camera/devices` | FFmpeg 枚举音视频采集设备 |
|
||
| 摄像头 | `GET/POST /camera/config` | 读写 `camera_live.ini` |
|
||
| 历史 | `GET /youtube/relay/sessions` | 转播会话 |
|
||
| 历史 | `POST /youtube/relay/sessions/import` | 从 PM2 日志导入 |
|
||
| 网络 | `GET /network_status` `GET/POST /proxy_config` | 测速与代理 |
|
||
| 系统 | `GET /system_metrics` `GET /host/gpu_status` | 主机与 NVENC |
|
||
| OAuth | `GET /youtube/oauth/*` | Google 拉取串流密钥(UI 可关) |
|
||
|
||
**可选鉴权**:`config/web2_api_token.txt` 或 `WEB2_API_TOKEN` 存在时,除 `/health` 外需:
|
||
|
||
```http
|
||
Authorization: Bearer <密钥>
|
||
```
|
||
|
||
Electron 主进程自动注入 API 鉴权头。
|
||
|
||
---
|
||
|
||
## 配置与数据路径
|
||
|
||
| 路径 | 用途 |
|
||
|------|------|
|
||
| `config/youtube.ini` | 单路密钥与 `[youtube]` 选项(GPU、分辨率、RTMPS) |
|
||
| `config/URL_config.ini` | 单路源站 URL 列表 |
|
||
| `config/youtube_channels.json` | Pro 频道元数据(见 `youtube_channels.example.json`) |
|
||
| `config/relay_pro/url_config.ch_*.ini` | 每频道源站地址 |
|
||
| `config/relay_pro/youtube.ch_*.ini` | 每频道密钥(后端物化) |
|
||
| `config/web2_api_token.txt` | API 鉴权密钥 |
|
||
| `config/web2_bind_host.txt` | 监听地址(懒人包默认 `127.0.0.1`;局域网访问可设 `0.0.0.0` 并配置 token) |
|
||
| `config/google_oauth.example.json` | YouTube OAuth 模板 |
|
||
| `config/ffmpeg_proxy.ini` | FFmpeg 代理 |
|
||
| `config/camera_live.ini` | 摄像头采集参数(见 `camera_live.example.ini`) |
|
||
| `backup_config/__web__/` | 配置版本备份 |
|
||
| `runtime/youtube_relay/sessions.sqlite` | 转播会话库 |
|
||
| 用户数据目录 `client-data.sqlite` | Electron 本地事件与快照 |
|
||
|
||
示例 `config/youtube_channels.json`:
|
||
|
||
```json
|
||
{
|
||
"version": 1,
|
||
"channels": [
|
||
{
|
||
"id": "ch_a",
|
||
"name": "路线A",
|
||
"douyinUrl": "https://live.douyin.com/123456789",
|
||
"youtubeKey": "xxxx-xxxx-xxxx-xxxx"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 单频道与多频道 Pro
|
||
|
||
### 单频道
|
||
|
||
1. 填写 `config/youtube.ini` 中的串流密钥。
|
||
2. 填写 `config/URL_config.ini` 中的抖音直播间地址。
|
||
3. **直播** 页选择 `youtube2` → **开始直播**。
|
||
|
||
### 多频道 Pro
|
||
|
||
1. 直播页打开 **Pro** 开关。
|
||
2. 界面新增频道,或编辑 `config/youtube_channels.json`。
|
||
3. 每频道进程:`youtube2__{channelId}`,独立密钥与 URL 文件。
|
||
4. 网格内按频道启停;预检要求密钥与源站均已配置。
|
||
|
||
---
|
||
|
||
## 推流诊断 / 质量守卫 / 转播历史
|
||
|
||
`GET /status` 的 `business_status` 示例:
|
||
|
||
| 状态 | 含义 |
|
||
|------|------|
|
||
| `streaming` | 正在推流 |
|
||
| `relay_slow` | 推流速度低于实时 |
|
||
| `source_stalled` | FFmpeg 进度停滞 |
|
||
| `youtube_key_rejected` | YouTube 拒绝 RTMPS |
|
||
| `waiting_source` | 等待源站开播 |
|
||
| `misconfigured` | 配置不完整 |
|
||
| `monitoring` | 在线监测中 |
|
||
|
||
**链路诊断**:`GET /youtube/diagnostics` → 源站 / FFmpeg / 目标三层检查与综合评分。
|
||
|
||
**质量守卫**:`GET /youtube/quality_guard` → FFmpeg 指标与告警(诊断层内部复用)。
|
||
|
||
**转播历史**:`runtime/youtube_relay/sessions.sqlite`
|
||
|
||
- PM2 `online` / 停止时自动开闭会话;
|
||
- `/status` 轮询时从日志同步主播与时长;
|
||
- 界面 **从日志导入** 可解析历史 PM2 输出。
|
||
|
||
---
|
||
|
||
## youLIVE 目标端监控
|
||
|
||
内嵌于 Electron 主进程的 **youLIVE** 模块(`electron/src/youlive/`),通过 preload 暴露 `window.youlive` API,为直播页提供 YouTube **目标端**能力,与 `web2` 控制的 **源站推流** 互补。
|
||
|
||
| 能力 | 说明 |
|
||
|------|------|
|
||
| **监听列表** | 按 YouTube 频道 / 直播页 URL 轮询开播状态、观众数 |
|
||
| **转播绑定** | 将监听地址写入 `youtube_channels.json` 的 `youtubeWatchUrl`,与 Pro 线路一一对应 |
|
||
| **弹幕抓取** | 直播进行中拉取聊天消息,支持关键词告警 |
|
||
| **桌面通知** | 推流未到达 YouTube、目标端下播、弹幕关键词命中时通知(需在 youLIVE 设置中开启) |
|
||
| **本地存储** | `youlive` SQLite 保存监听项、会话、告警历史 |
|
||
|
||
直播页 **YouTube 目标端监控** 面板在 Pro / 单路模式下自动同步监听地址;摄像头页亦可绑定 `youtube_watch_url` 做目标端校验。
|
||
|
||
---
|
||
|
||
## 摄像头直推
|
||
|
||
**摄像头** 页将本机物理摄像头 + 麦克风经 FFmpeg 直推 YouTube RTMPS,进程名 `camera_youtube`(与抖音转播 `youtube2` 独立)。
|
||
|
||
1. 在界面选择 **视频设备** / **音频设备**(后端 `GET /camera/devices` 枚举 DirectShow 设备)。
|
||
2. 设置分辨率、帧率、码率;可选 NVENC 硬件编码。
|
||
3. 填写 YouTube **串流密钥**(复用 `config/youtube.ini`)。
|
||
4. 可选填写 **YouTube 直播页地址** 供目标端监听。
|
||
5. 点击 **开始直播**。
|
||
|
||
配置持久化于 `config/camera_live.ini`(模板见 `config/camera_live.example.ini`)。
|
||
|
||
---
|
||
|
||
## 会员登录门禁(可选)
|
||
|
||
默认 **关闭**(无登录 UI,启动直播无账号要求)。
|
||
|
||
开启:**系统** → **客户端与系统集成** → **会员登录限制**
|
||
|
||
- 侧栏显示登录/注册;
|
||
- 开始/重启前需 PocketBase 会员(`X-PB-Token`);
|
||
- 状态键:`localStorage` → `pb_auth_gate_enabled`。
|
||
|
||
---
|
||
|
||
## 开发与构建
|
||
|
||
| 组件 | 版本 |
|
||
|------|------|
|
||
| Node.js | 18+ |
|
||
| pnpm | 10+ |
|
||
| Python | 3.10+(开发机;发布包自带运行时) |
|
||
|
||
| 命令(在 `electron/`) | 说明 |
|
||
|------------------------|------|
|
||
| `pnpm dev` | 开发模式 |
|
||
| `pnpm build` | 编译到 `out/` |
|
||
| `pnpm prepare:runtime` | 准备离线 Python/FFmpeg |
|
||
| `pnpm verify:runtime` | 校验运行时 |
|
||
| `pnpm dist` | Windows 便携包 |
|
||
|
||
---
|
||
|
||
## 打包发布
|
||
|
||
```bash
|
||
cd electron
|
||
pnpm install
|
||
pnpm dist
|
||
```
|
||
|
||
产物:`electron/dist/` 便携版。仓库根(除 `electron/`)打入 `resources/backend/`,用户机无需单独安装 Python。
|
||
|
||
---
|
||
|
||
## 环境变量
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `WEB2_PORT` | API 端口,默认 `8001` |
|
||
| `WEB2_HOST` | 监听地址(优先于 `web2_bind_host.txt`) |
|
||
| `WEB2_API_TOKEN` | API 密钥 |
|
||
| `WEB2_SUPERVISOR` | 进程后端;Pro 多频道勿强制 PM2 |
|
||
| `VITE_API_BASE` | 渲染进程 API 根(非 Electron 调试) |
|
||
| `VITE_WEB2_API_TOKEN` | 开发用 Bearer |
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
| 现象 | 处理 |
|
||
|------|------|
|
||
| 无法启动 / 服务未就绪 | 查 uvicorn 日志;确认 8001 未被占用;`pnpm verify:runtime` |
|
||
| YouTube 无画面 | 看 `youtube_key_rejected`;核对 Studio 密钥;检查 RTMPS 与代理 |
|
||
| `relay_slow` / 掉帧 | 查 NVENC;降分辨率;关占用 CPU 的程序 |
|
||
| Pro 无法启动 | 勿 `WEB2_SUPERVISOR=pm2`;每频道密钥与 URL 已保存;检查配对冲突横幅 |
|
||
| 摄像头无画面 | 确认 DirectShow 设备名与 `camera_live.ini` 一致;尝试关闭 GPU 编码 |
|
||
| 目标端监听无数据 | 确认 `youtubeWatchUrl` / `youtube_watch_url` 已填写;youLIVE 桌面通知已开启 |
|
||
| 配置误改 | 直播页 **历史备份** 或 `POST /config/restore` |
|
||
|
||
日志:
|
||
|
||
- Worker:`.pm2/logs/` 或界面「当前直播日志」
|
||
- 客户端:系统页打开「客户端日志」目录
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
| 文档 | 说明 |
|
||
|------|------|
|
||
| [docs/YOUTUBE_LIVE_SEO.md](docs/YOUTUBE_LIVE_SEO.md) | YouTube 直播 SEO |
|
||
| [docs/REALTIME_AUDIO_DEMUCS.md](docs/REALTIME_AUDIO_DEMUCS.md) | 实时音频 Demucs |
|
||
|
||
---
|
||
|
||
## 许可证
|
||
|
||
本项目继承上游 DouyinLiveRecorder 及相关依赖的许可证条款。使用第三方平台直播服务请遵守各平台服务条款。
|