批量引擎改为「分块流水线」:视频按 WOV_BATCH_STAGE_GROUP_SIZE(默认 8)分组, 组内按 DAG 拓扑序跑完全部视频(全部 extract → 全部 ASR → 全部翻译 → 全部 ASS) 再进入下一组,本地模型每组只加载一次、卸载一次,而不是每个视频来回加载卸载; 产物仍按组增量落到视频旁。调度器新增 execute_run(run_id, stop_after=节点): 该节点完成后任务保持 RUNNING 不收尾,下一次调用从产物表跳过已完成节点继续, 用于实现阶段边界。 - nodes/llm.py:翻译节点结束释放本机 Ollama 显存(node 参数 unload_after > LLM_UNLOAD_AFTER > 本机 loopback 端点默认卸载,云端端点不卸载;卸载失败只告警), 新增 keep_model.flag 语义(阶段内保持常驻)与 release_local_model(); 新增节点内暂停(按批 20 行检查 paused.flag,抛 PauseRequested,调度器保持 PAUSED)。 - src/wov_app/batch.py:分组阶段执行与阶段末统一释放显存;失败视频只在它失败 节点的那个阶段重试(避免 LLM 已常驻时重跑 ASR 抢显存);任务没有明细时保持 QUEUED 等登记完成、仍有未完成视频时置回 QUEUED 自愈(原先留 RUNNING 会卡死: 引擎只拾取 QUEUED,任务停在“运行中但没人推进”);无失败视频时删除任务级空目录; 每个阶段开始前清理 paused.flag / keep_model.flag,避免强杀残留影响后续阶段。 - src/wov_app/config.py:新增 WOV_BATCH_STAGE_GROUP_SIZE(设为 1 即旧的每视频全链路)。 - 任务列表与批量页分工:GET /api/runs 默认排除 source=batch(一个批量任务会产生 N 条单视频 run,会把 20 条窗口占满;且任务管理页的暂停/重试/删除对批量 run 语义不成立),需要排查时用 include_batch=1;作为补偿批量页详情新增阶段列 (阶段 i/N · 中文标签,由该视频 run 的 current_node_id 在 DAG 拓扑序中的位置 推导,节点类型映射中文标签)。阶段只有节点边界粒度,句级进度不落库、只在日志。 - 顺带纳入此前未提交的批量僵尸状态恢复:recover_interrupted_batch_jobs 除 RUNNING 外也把「COMPLETED 但仍含未结束视频」的任务置回 QUEUED;fix_zombie_batch_jobs.py 改为按条件扫描并支持 --apply 预览;批量页明细只列本批真正处理过的视频。 测试新增/更新:分块流水线调用顺序(组内按节点跑完再下一组)、每组只释放一次模型、 阶段内保持常驻标志、翻译按批暂停、失败视频不跨阶段推进、任务无明细/中途登记视频时 置回 QUEUED、任务工作空间与残留信号清理、任务列表默认过滤批量 run、详情阶段字段、 前端阶段列渲染;全量 507 passed(唯一失败为既有素材缺失的 integration 用例)。
3.7 KiB
3.7 KiB
配置与启动
启动
uv sync
uv run uvicorn wov_app.main:app --reload
访问:
http://127.0.0.1:8000/ 应用中心(上传视频 → 字幕生成)
http://127.0.0.1:8000/tasks.html 任务管理
http://127.0.0.1:8000/batch.html 批量处理(按文件夹)
http://127.0.0.1:8000/admin.html 管理后台(工作流)
http://127.0.0.1:8000/workflow.html 工作流编排(DAG JSON)
http://127.0.0.1:8000/docs API 文档
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
WOV_DATA_DIR |
<根>/data |
数据目录 |
WOV_DB_PATH |
<根>/data/wov.db |
SQLite 路径 |
WOV_STORAGE_DIR |
<根>/data/storage |
上传与产物根目录 |
WOV_AUTO_SEED |
1 |
启动时创建内置工作流 |
WOV_SCHEDULER_ENABLED |
1 |
启动后台调度器 |
WOV_SCHEDULER_INTERVAL_SECONDS |
1.0 |
调度轮询间隔 |
WOV_CLEANUP_ENABLED |
1 |
开启孤儿数据定时清理 |
WOV_CLEANUP_INTERVAL_SECONDS |
3600 |
孤儿清理扫描周期(秒) |
WOV_CLEANUP_GRACE_SECONDS |
3600 |
孤儿清理宽限期(秒) |
WOV_BATCH_ENABLED |
1 |
开启文件夹批量处理引擎(处理 source=batch 任务) |
WOV_BATCH_INTERVAL_SECONDS |
1.0 |
批量引擎轮询间隔 |
WOV_BATCH_STAGE_GROUP_SIZE |
8 |
批量「分块流水线」分组大小:每组视频按节点顺序跑完全部阶段(全部 extract → 全部 ASR → 全部翻译 → 全部 ASS)再进入下一组,本地模型每组只加载一次;设为 1 等价于每个视频各跑完整链路(产物逐视频落地最及时) |
WOV_AUTO_VAD |
1 |
开启每视频自适应 VAD 调参(详见 adaptive_vad.md) |
WHISPER_MODEL_PATH |
见 模型权重解析 | 显式指定 whisper 模型路径 |
WHISPER_DEVICE |
auto |
转写设备 |
LLM_API_BASE |
https://api.siliconflow.cn/v1/chat/completions |
LLM 兼容接口 |
LLM_API_KEY |
空(读 .env) |
SiliconFlow Bearer Key,存于 gitignored 的 .env |
LLM_MODEL |
Qwen/Qwen3.5-35B-A3B |
LLM 模型名(默认值与例外说明见 decisions.md) |
LLM_TIMEOUT_SECONDS |
600 |
LLM 单请求超时(llm-filter 内部默认 60) |
LLM_UNLOAD_AFTER |
空(按端点自动) | llm-translate 结束后是否卸载本地模型:空=端点在本机时卸载(把显存让给后续 whisper 等节点)、1 强制卸载、0 关闭;节点参数 unload_after 优先级更高 |
OLLAMA_HOST |
http://192.168.123.70:11434 |
Ollama 服务地址 |
VLM_MODEL |
glm-ocr:latest |
VLM OCR 模型 |
VLM_PROMPT |
提取图像中的文字,不要描述图片中的内容 | OCR 提示词(字幕流水线在 ocr-subtitle 工作流的 subtitle-ocr 节点参数中显式指定同一提示词) |
VLM_TIMEOUT_SECONDS |
5 |
VLM 单请求整体超时上限(每次调用 5 秒,超时即终止;流式读取同样受此截止约束) |
FFMPEG_BIN |
空 | 显式 ffmpeg 路径(否则 PATH → imageio-ffmpeg) |
Python 环境与 uv 管理
- 统一使用 uv 管理虚拟环境和依赖,禁止直接使用 pip 修改依赖。
- 基础命令:
uv sync(安装含 dev 组依赖)、uv run <command>、uv add <package>、uv lock。 - 虚拟环境位于
.venv,测试依赖在[dependency-groups] dev。 - 新增依赖时使用
uv add,不修改系统 Python 或全局环境。
相关文档
- 本地模型权重目录:node-protocol.md
- 运维语义(清理、暂停、批量):operations.md