文章

把长视频字幕做成可恢复流水线:Qwen3-ASR Subtitle Studio

一个把媒体预处理、VAD、外部 ASR、翻译、人工校对和字幕导出拆成可恢复步骤的独立工作台。

把长视频字幕做成可恢复流水线:Qwen3-ASR Subtitle Studio

长视频字幕看起来像一条直线:上传视频,调用 ASR,再导出 SRT。但实际跑过几小时素材后就会发现,最昂贵的不是某一次模型请求,而是失败后的重来。音频切到一半、某个 ASR chunk 超时、翻译批次少回一条、人工已经改过文本——如果系统只有一个“开始”按钮,任何局部错误都可能迫使整条流程重跑。

我最近把 qwen3-asr-subtitle-studio 作为独立项目发布。它把媒体标准化、Silero VAD、外部 Qwen3-ASR、可选 LLM 翻译/润色、人工编辑和 SRT/VTT/ASS 导出组织成一条可恢复的持久化流水线。

工作台与模型服务解耦

仓库不包含 Qwen3-ASR 源码、模型权重或 GPU 推理容器。字幕工作台只依赖外部 Gradio /run 接口,模型服务可以在另一台有 GPU 的机器上独立部署。

整体结构是:

1
2
3
4
5
6
浏览器
  -> React / Nginx 前端
  -> FastAPI 后端
       -> FFmpeg + Silero VAD + SQLite
       -> 外部 Qwen3-ASR Gradio 服务
       -> 可选 OpenAI-compatible LLM

这个边界让前后端可以独立升级,也避免把数 GB 权重塞进应用仓库。Compose 只管理字幕前后端,停止工作台不会顺手关闭外部 ASR 服务。

ASR 适配器要求服务提供机器可读 schema、音频上传、语言参数和 return_ts=true。返回至少包含语言、文本与时间戳,时间字段可以是毫秒或秒,但必须能转换为统一格式。启动前检查 /gradio_api/info,比在第一条长视频处理到中间时才发现接口不兼容更划算。

上传后只保留标准音频

用户可以导入 MP4、MKV、MOV、MP3、WAV 或 M4A。后端先用 FFmpeg 提取 16 kHz 单声道 WAV,成功后立即删除原视频或原音频,避免服务端长期保存体积大且更敏感的原媒体。

项目目录只留下处理所需的音频、VAD chunk、ASR 原始响应和最终导出。删除项目时文件先进入 data/.trash,服务启动也会清理异常残留的源媒体。这个策略兼顾了故障恢复与数据最小化:保留能够继续工作的中间证据,不把原素材无限期堆积在服务器上。

每个步骤都拥有自己的状态

一键流程并不是一个巨大函数。VAD、ASR chunk 和 LLM batch 都独立持久化,并有 pending、running、failed、completed 等状态。再次执行时只继续未完成或失败单元,不重复处理已经成功的部分。

批量导入最多支持 100 个媒体文件,ASR 侧按文件串行使用外部服务,失败任务可以单独重试。这种节制比盲目并发更适合单卡推理服务:把请求队列堆满并不会增加显存,只会让超时和恢复更难判断。

任务状态与产物要一起落盘。只记录“步骤完成”却没有可读取的响应文件,会制造幽灵成功;只有文件存在却没有数据库状态,又无法安全判断是否可以复用。二者必须在明确的提交边界内更新。

原文、润色和翻译是不同产品模式

工作台提供四条路径:原文直出、听写后仅润色、仅翻译、翻译加保守润色。只有后三种需要 LLM 凭据,原文字幕完全可以只依赖 ASR。

翻译 API 使用 OpenAI-compatible Chat Completions,并要求结构化返回:每个 segment 的 ID、数量和顺序都必须与请求一致。LLM 只修改文本,不允许改时间戳。后续 batch 可以读取前序文本作为上下文,但不能反向重写已经确定的时间轴。

这种约束牺牲了一点“自由发挥”,换来的是可验证性。少一条、多一条或 ID 错位都直接判为失败,而不是把看似流畅的文本错配到另一句字幕上。

人工编辑不是流程之外的补丁

ASR 和翻译之后,用户可以编辑文本、锁定文本或排版,执行合并、拆分、新增和删除,再导出 SRT、VTT 或 ASS。锁的意义是让后续自动步骤尊重人工决定,避免一次重跑覆盖已经校正的专有名词或断句。

可恢复系统的最终目标不是让机器步骤永不失败,而是让自动处理和人工修订能够安全交替。只要状态、产物和锁定语义清楚,一次局部失败就只是一个待处理单元,不再是整条长视频的灾难。

项目地址:cyijun/qwen3-asr-subtitle-studio

本文由作者按照 CC BY 4.0 进行授权