19 KiB
videoroll
模块化视频处理流水线:内容接入 -> 字幕/翻译 -> 压制/封装 -> 可选投稿到哔哩哔哩。
当前重点是带 RAG Agent 的视频字幕翻译:在翻译每个字幕 block 之前,系统会先判断哪些词真的需要知识库或联网查证,再把可信术语和背景知识注入翻译 prompt。目标不是把所有词都入库,而是解决 YouTube、动漫、游戏实况、技术讲解这类视频里“模型缺上下文”的问题。
详细规格见 docs/PROJECT_SPEC.md。
显著功能
- 主 Agent + 子 Agent 翻译 RAG:字幕翻译前由主 Agent 扫描当前 block 和前文 summary,决定哪些术语需要研究;每个术语由独立子 Agent 维护 observation/evidence 上下文并选择工具。
- PostgreSQL + pgvector 知识库:术语、译法、来源、置信度和使用次数统一入库;支持向量检索、手动新增/删除条目、重建 embedding。
- 真正的工具调用循环:子 Agent 可按需调用
rag_lookup、wiki_search、search_web、fetch_url、finish,而不是固定按 wiki -> search 的流水线机械执行。 - 轻量 Agent Runtime:内部运行时统一管理 tool schema、LLM/tool/fetch 预算、状态迁移、错误类型和 trace 字段,方便后续扩展 Dictionary/Wiki/GitHub/Bilibili 等工具。
- Wikipedia Tool + SearXNG Tool:固定 English Wikipedia API 用于通用百科知识;自建 SearXNG 用于补充网络搜索;搜索摘要不足时可继续读取网页正文。
- 并发术语研究 Agent:可在
Settings -> Translate设置并发数和超时;主 Agent 等待子 Agent 返回结构化结果后再合并进当前 block 翻译。 - 保守入库策略:summarize -> verify -> write_rag;只有 verifier 判断来源支撑、上下文一致且置信度足够时才正式入库,否则标记为 pending、context_only 或 skipped。
- 独立模型配置:翻译大模型、embedding 模型的 API key/base URL 分开;翻译大模型支持单独设置失败重试次数;embedding 支持 OpenAI 兼容服务和本地模型。
- 可观测 Dashboard:显示任务状态、CPU/内存/Intel GPU 资源监控,以及 RAG Agent 当前运行状态和历史对话流。
- 完整 Web 配置:ASR、翻译、RAG、YouTube、Bilibili、自动模式、知识库均可在 Web UI 中配置,减少部署环境变量依赖。
当前状态
- Web UI 已接入管理密码登录,首次打开需要设置 admin password。
- 后端容器会同时启动
uvicorn、字幕 Celery worker、投稿 Celery worker。 - YouTube 下载统一使用
yt-dlp默认格式选择,不再额外强制mp4+m4a。 - YouTube 支持在 Web UI 中配置代理、测试出口连通性、保存
cookies.txt,并显示 cookies 摘要。 - 若未配置
YOUTUBE_COOKIE_FILE,已保存到数据库的 YouTube cookies 会在下载/元信息提取时写入临时文件供yt-dlp使用。 - YouTube 触发风控时,接口会返回更明确的 cookies / proxy 提示。
- Bilibili 投稿支持在 Web UI 中保存 Cookie、测试登录、维护默认投稿模板。
- Web UI 支持浅色 / 暗色模式切换,Dashboard 增加 CPU、内存和 Intel GPU 资源监控。
- 字幕翻译支持真正的 RAG 术语知识库:可使用 PostgreSQL + pgvector 检索术语,支持本地 embedding 模型、手动下载模型、重建向量,以及 Agent 自动发现/搜索/验证/入库术语。
- RAG Agent 已改为主 Agent / 子 Agent 结构:Dashboard 可查看主 Agent、其下属子 Agent、每一步工具调用、耗时、模型、错误类型和 JSON 输入输出。
架构概览
当前默认部署使用单容器应用服务:
app运行videoroll.apps.monolith.main:app挂载子服务:/api/api/subtitle-service/api/youtube-ingest/api/bilibili-publisher同时启动两个 Celery worker:subtitlepublish
web提供前端 UI,并将同源/api反代到后端redisCelery broker / backendminio资产存储postgresql需要你自行提供;当前仓库的 compose 文件不再内置 PostgreSQL
环境要求
- Docker Engine + Docker Compose Plugin
- 一个可用的 PostgreSQL 16+ 实例
- 访问 YouTube 所需的网络环境
- 如果要使用真实 ASR:
INSTALL_ASR=1
可选但常见:
- Python 3.12+,用于本地运行辅助脚本
- Node.js 20+,用于单独启动前端开发服务器
./scripts/dev_web.sh
安装与启动
1. 克隆仓库
git clone git@github.com:kelriclink/videoroll.git
cd videoroll
2. 准备 PostgreSQL
当前 compose 不会帮你起数据库,你需要自己提供一个 PostgreSQL,并把它暴露给 app 容器。
一种简单方式是在宿主机单独跑一个 PostgreSQL:
docker run -d \
--name videoroll-postgres \
-e POSTGRES_USER=videoroll \
-e POSTGRES_PASSWORD=videoroll \
-e POSTGRES_DB=videoroll \
-p 5432:5432 \
postgres:16
3. 创建 .env
cp .env.example .env
至少确认这些变量:
DATABASE_URLREDIS_URLS3_*INSTALL_ASR
如果数据库跑在宿主机,推荐这样配置:
DATABASE_URL=postgresql+psycopg://videoroll:videoroll@host.docker.internal:5432/videoroll
REDIS_URL=redis://redis:6379/0
S3_ENDPOINT_URL=http://minio:9000
S3_ACCESS_KEY_ID=videoroll
S3_SECRET_ACCESS_KEY=videorollsecret
S3_BUCKET=videoroll
S3_REGION_NAME=us-east-1
S3_USE_SSL=false
说明:
app容器已注入host.docker.internal映射,因此 Linux/macOS/Windows 都可以按这个地址连接宿主机数据库。- 如果你的 PostgreSQL 在别的主机或别的 Docker 网络里,把
host.docker.internal改成实际地址即可。
4. 启动服务
推荐直接使用仓库脚本:
./scripts/dev_up.sh
如果你想手动启动,请显式指定 compose 文件,避免仓库里同时存在 compose.yml 和 docker-compose.yml 时的歧义:
docker compose -f docker-compose.yml --env-file .env up --build -d
5. 使用已导出的镜像部署
如果你从 dist/docker-images/videoroll-prod-app-web.tar 部署:
docker load -i dist/docker-images/videoroll-prod-app-web.tar
docker compose -f docker-compose.yml --env-file .env up -d
该 tar 只包含业务镜像:
videoroll:prodvideoroll-web:prod
Redis、MinIO、PostgreSQL 仍按 compose 或你的现有部署提供。导出后可用 sha256 文件校验:
sha256sum -c dist/docker-images/videoroll-prod-app-web.tar.sha256
6. 首次登录
打开 Web UI:
http://localhost:3000
首次访问会进入 admin password 初始化页面:
- 第一次使用:设置管理密码
- 后续新设备或浏览器数据被清除后:输入管理密码登录
这是设备记住模式,密码不会每次都要求输入。
主要访问地址
- Web UI:
http://localhost:3000 - Orchestrator API:
http://localhost:3000/api/docs - Subtitle Service:
http://localhost:3000/api/subtitle-service/docs - YouTube Ingest:
http://localhost:3000/api/youtube-ingest/docs - Bilibili Publisher:
http://localhost:3000/api/bilibili-publisher/docs - MinIO Console:
http://localhost:9001
健康检查:
./scripts/dev_health.sh
查看日志:
./scripts/dev_logs.sh
停止服务:
./scripts/dev_down.sh
目录与持久化数据
data/minioMinIO 数据目录data/modelsASR / embedding 模型目录(可存放 faster-whisper、OpenVINO Whisper 导出模型、本地 embedding 模型)data/secrets本地密钥和机密目录data/secrets/fernet.key首次保存加密配置时自动生成,用于加密存储 OpenAI key、YouTube cookies、Bilibili cookies 等敏感数据
不要随意删除 data/secrets/fernet.key,否则之前存储在数据库里的加密配置将无法解密。
配置说明
核心环境变量
DATABASE_URLPostgreSQL 连接串REDIS_URLRedis 连接串S3_ENDPOINT_URLMinIO / S3 地址S3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYS3_BUCKETS3_REGION_NAMES3_USE_SSLFFMPEG_PATH默认ffmpegWORK_DIR默认/tmp/videorollINSTALL_ASR1时构建真实 ASR 依赖;0时减小镜像体积SUBTITLE_ASR_ENGINE默认 ASR 引擎,支持faster-whisper/openvino/mockSUBTITLE_WHISPER_MODEL_DIRASR 模型目录,默认/models/whisperSUBTITLE_OPENVINO_MODELOpenVINO Whisper 模型目录(可选;也可在 UI 的 ASR 设置里保存默认模型路径)SUBTITLE_OPENVINO_DEVICEOpenVINO 推理设备,默认GPUSUBTITLE_OPENVINO_NUM_BEAMSOpenVINO 默认 beam size,默认1SUBTITLE_OPENVINO_MAX_NEW_TOKENSOpenVINO 默认max_new_tokens,默认448PUBLISH_ADDRWeb / MinIO console 的监听地址,默认127.0.0.1WEB_PORTWeb 端口,默认3000MINIO_CONSOLE_PORTMinIO console 端口,默认9001
YouTube 配置
推荐通过 Web UI 管理:
Settings -> YouTube
支持的内容:
- 保存 / 清空代理
- 测试指定 URL 是否能通过当前代理访问
- 粘贴并保存 Netscape 格式的
cookies.txt - 启用或禁用已保存 cookies
- 查看 cookies 是否包含登录态 / 是否可能包含 bot-check 豁免
当前默认行为:
- 下载直接使用
yt-dlp默认格式选择 - 不再提供
YOUTUBE_YTDLP_FORMAT - 默认
User-Agent为浏览器 UA,而不是自定义短 UA
可选环境变量:
YOUTUBE_USER_AGENTYOUTUBE_COOKIE_FILEYOUTUBE_PROXYYOUTUBE_EXTRACTOR_ARGS_JSON
说明:
YOUTUBE_COOKIE_FILE是可选的;如果不配,系统会优先使用你在 UI 中保存的 cookies。YOUTUBE_EXTRACTOR_ARGS_JSON用于高级场景,例如:
YOUTUBE_EXTRACTOR_ARGS_JSON={"youtube":{"player_client":["tv","android_sdkless","web"]}}
YouTube 风控注意事项:
- 浏览器导出 cookies 时,请使用和服务端相同的代理 / 出口 IP。
- 如果浏览器中出现过“确认你不是机器人”,通常需要在同一出口 IP 下先完成验证,再重新导出 cookies。
- 只有
VISITOR_INFO1_LIVE一类 cookie 通常不够,建议确保 cookies 中包含登录态。 - YouTube cookies 轮换很快,过期后需要重新导出。
ASR / 翻译 / 自动模式
相关页面:
Settings -> ASRSettings -> TranslateSettings -> AutoDashboard
说明:
- 默认 ASR 为
faster-whisper - 也支持
openvino(方案 2:在现有subtitle-service进程内直接跑 OpenVINO Whisper,适合 Intel Arc / Intel GPU) Settings -> Auto用于配置 YouTube 自动模式的默认参数:- 字幕格式
- 是否 burn-in / soft-sub
- 编码参数
- 翻译目标语言与 provider
- 是否自动投稿 Bilibili
Dashboard会显示任务状态、资源监控、RAG Agent 当前运行状态和历史 trace。
如果只是想做轻量演示,可把:
INSTALL_ASR=0
SUBTITLE_ASR_ENGINE=mock
如果要启用 openvino:
INSTALL_ASR=1
SUBTITLE_ASR_ENGINE=openvino
SUBTITLE_OPENVINO_DEVICE=GPU
SUBTITLE_OPENVINO_MODEL=/models/whisper/whisper-large-v3-ov
说明:
openvino需要一个 OpenVINO Whisper 模型目录。- 现在支持在
Settings -> ASR里直接下载 OpenVINO 官方预转换模型;输入tiny/base/small/medium/large-v3时会自动映射到对应的OpenVINO/whisper-*-fp16-ov仓库。 - 也支持手工准备模型:可以在宿主机先用
optimum-cli export openvino --model openai/whisper-large-v3 <output_dir>生成,再挂载/上传到data/models。 - 下载或上传后,在
Settings -> ASR中把默认引擎切到openvino,并配置device / num_beams / max_new_tokens。
翻译 RAG / Agent
相关页面:
Settings -> TranslateDashboard -> RAG Agent
RAG 用于解决视频字幕翻译中的上下文和术语问题,例如游戏、动漫、技术讲解中的专有名词、缩写、黑话和社区固定译法。
当前流程:
字幕片段
+ 前文翻译 summary
-> 主 Agent 创建 rag_master run
-> RAG gate 判断哪些术语需要检索
-> 查询 PostgreSQL/pgvector 知识库
-> 未命中时并发启动子 Agent
-> 子 Agent 自己决定调用 rag_lookup / wiki_search / search_web / fetch_url / finish
-> 子 Agent 收集证据并总结候选术语
-> verifier 检查来源和上下文
-> 写入知识库或标记为 context_only / skipped
-> 子 Agent 返回 AgentResearchResult
-> 主 Agent 汇总 term_cards / knowledge_cards / hits
-> 翻译时注入 RagContext
关键行为:
- 单字母变量(如逻辑课里的
P/Q/R)默认视为局部变量,不搜索、不写入长期知识库。 - 常见基础术语(如
truth table)可以作为本次翻译提示,但默认不自动污染长期知识库。 - 自动正式入库要求 verifier 通过、上下文一致、有有效外部来源,并达到较高置信度;否则进入待审核或跳过。
- Wikipedia Tool 使用固定 English Wikipedia API,不需要额外配置 wiki 地址;它适合通用百科类专有名词,不替代垂直领域资料库。
- SearXNG Tool 使用 base URL 配置,系统自动拼接
/search?q=...&format=json,并过滤搜索引擎 About/Preferences 等内部页面。 - SearXNG 支持在 Web UI 配置
categories、engines、fallback_engines、language、safesearch、time_range和pageno;默认使用categories=general、language=all、safesearch=0、pageno=1,默认搜索为空时 fallback 到bing,baidu。 - 可在
Settings -> Translate调整 Agent 并发数、Agent 超时、大模型失败重试次数。并发越高,术语补全越快,但外部 API、LLM 和搜索服务压力也越大。 - Dashboard 中可以点击主 Agent 查看下属子 Agent;点击子 Agent 可查看它自己的工具调用对话流。
- 每个 Agent trace 都会带
event_id、span_id、status、工具 schema、耗时、错误类型和预算计数,便于排查哪个节点失败或耗时过长。
子 Agent 返回主 Agent 的数据是结构化结果,而不是把整段 trace 直接塞回 prompt:
AgentResearchResult
- hit: 成功写入或命中的长期知识库条目
- context_card: 不适合长期入库但当前 block 可用的临时术语提示
- normalized_term: 去重用的规范化术语
主 Agent 会把这些结果合并成 RagContext,后续翻译 prompt 只注入精简后的术语卡片和知识卡片,避免长 trace 拖慢翻译。
PostgreSQL 需要启用 pgvector:
CREATE EXTENSION IF NOT EXISTS vector;
如果应用账号不是数据库超级用户,请用数据库管理员账号先在目标库执行上面的 SQL。
SearXNG 搜索地址建议填写 base URL,例如:
https://search.example.com
系统会自动请求 /search?q=...&format=json,不需要在配置里手写 ?q=。
可选搜索参数在 Settings -> Translate -> RAG Agent 配置:
categories=general
engines=
fallback_engines=bing,baidu
language=all
safesearch=0
time_range=
pageno=1
engines 为空时使用 SearXNG 实例默认引擎;常见值包括 bing、baidu、brave、duckduckgo、wikipedia、arxiv、pubmed、github、stackoverflow、youtube 等。最终可用引擎以你自己的 SearXNG settings.yml 为准。
Embedding 支持两种方式:
- OpenAI 兼容 embedding:填写 provider 支持的 embedding 模型名、base URL 和独立 API key。
- 本地 embedding:在
Settings -> Translate中选择本地 provider,可手动下载模型到data/models,并选择 CPU / OpenVINO GPU 等设备。
更换 embedding 模型后,已有知识库向量不会静默重建;需要在 Settings -> Translate 中点击重建按钮,避免模型切换时旧向量和新向量混用。
Dashboard 资源监控
Dashboard 会定时显示:
- CPU 使用率和 load average
- 内存使用率
- 启用自动模式并配置 Intel GPU 时的 Intel GPU 状态
- 正在运行和最近完成的 RAG Agent
Intel GPU 使用率依赖宿主机和容器能读取对应设备/驱动信息;如果 busy 不可读,页面会显示不可读原因,但不影响其他流程。
Bilibili 配置
相关页面:
Settings -> Bilibili
支持:
- 保存 Bilibili Cookie
- 检查是否成功解析出
SESSDATA和bili_jct - 测试当前 Cookie 是否可登录
- 保存默认投稿模板
default_meta
真实投稿前,建议至少确认:
- Cookie 有效
- 含
bili_jct - 默认模板里的分区、标签、简介符合你的账号需求
使用流程
本地视频
New Task -> 本地上传- 上传视频
- 在任务详情页执行字幕、翻译、压制、投稿
YouTube 手动模式
New Task -> YouTube 链接- 填写授权类型和可选证明链接
- 创建任务
- 在任务详情页手动执行:
- 获取元信息
- 下载 YouTube 视频
- 生成字幕 / 翻译
- 压制或投稿
YouTube 自动模式
- 先在
Settings -> Auto配好默认参数 New Task -> YouTube 自动模式- 系统会按配置执行:
- 下载
- 字幕 / 翻译
- burn-in 或 soft-sub
- 可选自动投稿 Bilibili
常见问题
1. 启动后直接报数据库连接错误
优先检查:
- PostgreSQL 是否真的已经启动
.env里的DATABASE_URL是否指向了可达地址- 如果数据库在宿主机,是否使用了
host.docker.internal
2. 打开页面后要求设置或输入密码
这是预期行为。所有非 /auth/* 和 /health 接口都受 admin 设备登录保护。
3. YouTube 下载报 Sign in to confirm you're not a bot
先检查:
- 当前网络 / 代理是否可稳定访问 YouTube
- 是否已经在
Settings -> YouTube保存有效的cookies.txt - cookies 是否包含登录态
- 导出 cookies 时是否使用了同一代理 / 同一出口 IP
4. YouTube 下载报 Requested format is not available
当前代码已经统一改成 yt-dlp 默认格式选择;如果你还看到这个错误,通常不是项目手写格式规则的问题,而是:
- YouTube 当前返回的可用流本身异常
- cookies / 风控导致某些格式不可见
yt-dlp/ YouTube 抽取链路临时波动
优先更新 cookies、检查代理,再看是否需要调整 YOUTUBE_EXTRACTOR_ARGS_JSON。
5. OpenAI 配置存在哪里
OpenAI 配置通过 Web UI 保存到数据库,密钥内容用 data/secrets/fernet.key 加密。
前端开发模式
如果你只想本地调前端:
./scripts/dev_web.sh
这会在 src/web 下启动 Vite dev server。默认情况下,生产部署仍建议使用 web 容器。
合规边界
本项目仅用于处理你拥有版权、已获授权、或明确允许再分发的视频内容。不要将其用于批量搬运、绕过平台限制、或处理无授权内容。