短剧本地化拿到的素材,往往只有一个 MP4:没有剧本、角色表和分轨音频,却需要输出多角色英文配音、保留背景音乐,并让字幕与画面保持同步。模型能够识别、翻译和合成一句话,工程系统还要解决另一件事:改错一句台词后,怎样只重做受影响的部分。
这篇文章记录 Dubora 配音流水线的实现。自动执行覆盖音频处理到成片输出,原文校准和译文审阅保留两个人工关卡。“自动化”指重复加工由系统承担,角色归属、翻译含义和成片质量仍有明确的审核入口。
以下按 2026 年 3 月 20 日的工程版本说明。早期实现使用 JSON 文件管理字幕与配音模型,后来将可编辑数据迁入数据库,并把断句、对齐收进相应阶段。本文中的阶段数量、数据归属和增量策略都以这一版本为准。
一、七个阶段,两个审核关卡
流水线分为 7 个 Phase,在界面上归入提取、识别、翻译、配音、合成 5 个 Stage。Phase 是加工动作,Gate 是暂停等待确认的条件,两者不能混算。
| 阶段 | 主要工作 | 结果 |
|---|---|---|
| Extract | 提取音频、分离人声与伴奏 | 音频文件 |
| ASR | 识别文字与说话人标签 | 原始识别响应 |
| Parse | 断句、整理时间轴和情绪信息 | 数据库中的原文字幕条目 |
| Translate | 按台词组翻译,回填字幕条目 | 译文及 TTS 时间策略 |
| TTS | 按角色声线逐段合成 | WAV 文件及逐段合成记录 |
| Mix | 在原时间轴放置配音并混入伴奏 | 混音文件 |
| Burn | 生成字幕并烧录到视频 | 英文配音成片 |
Parse 之后是 source_review,检查原文、说话人和时间位置;Translate 之后是 translation_review,检查译文,再进入语音合成。这使人工修改发生在昂贵的下游加工之前。
数据有明确归属,文件用于保留证据和交付
这一版本使用 SQLite 保存业务元数据。cues 是可编辑的字幕条目,utterances 表示翻译和合成使用的台词组,两者通过关联表连接;角色音色、任务状态和产物记录也进入数据库。ASR 原始响应、音频和成片仍以文件保存。
这里的“单一事实来源”按对象划分:人工确认的字幕以数据库为准,识别原始响应用于追溯,WAV 和 SRT 是加工产物。不能把三份都允许独立修改的 JSON 同时叫作同一份台词的事实来源,否则修改究竟从哪里生效就不清楚了。
二、从音频到可校准的台词
2.1 分离的目的,是得到可复用的伴奏轨
直接用新配音覆盖原声,会让两个语言的人声叠在一起。Extract 使用 FFmpeg 提取音频,再通过 Demucs 分离人声与伴奏,供识别和最终混音使用。
Demucs 的官方说明主要面向音乐源分离。--two-stems=vocals 可以输出人声和其余声部,但不意味着模型只计算两个声部,也不能由音乐基准直接推导短剧对白的识别收益。背景音乐、混响和重叠对白都可能留下分离残留,应结合听感检查。
音频格式也要按用途处理:ASR 的输入规格不能直接当作母带规格。需要 16 kHz 单声道的识别服务,可以使用单独转换的输入;伴奏和交付音轨应保留满足输出要求的质量,避免先降采样再期待混音恢复细节。是否把分离后的人声送入 ASR,是需要用实际片段比较的配置选择。
2.2 识别说话人,不等于识别角色
项目接入豆包 ASR,保存服务原始响应,再解析文字、词级时间信息和说话人标签。不同接口和版本返回的字段不同,后处理必须依据实际响应,不能假定任何 ASR 都提供情绪和性别。
最容易影响配音的错误,是同一角色在不同片段被分成多个 speaker,或者一个短句被归到另一个 speaker。speaker=1 只是这次识别得到的分组标签,不能直接理解为跨集稳定的角色身份。最终声线分配需要人工确认角色归属。
词级时间戳让断句能够沿已有语音位置切分,但“使用毫秒作为单位”不代表边界准确到毫秒。快速对白、重叠发言和背景噪声都需要回听校准。
2.3 Parse 把识别结果变成编辑对象
Parse 先按照停顿、说话人变化和时长约束整理台词,再按配置调用 LLM 做语义断句与情绪修正,最终写入数据库。旧版独立的 Reseg 已合并到这个阶段。
这一版本的配置包含 450 ms 静音拆分阈值和 8 秒最大台词时长。它们是项目默认参数,目的是避免长句过长或字幕过碎,需要针对素材调整。
有三个约束比具体阈值更重要:
- 不把不同说话人的词合成同一段配音台词
- 语义拆分后保留原文完整性,并检查新增边界是否落在合理位置
- 情绪描述属于这句台词的表达状态,不能因为数据结构将它放在 speaker 对象里,就当成角色永久属性
2.4 校准界面让人工修改进入正式流程
校准工具把播放器、台词列表和时间轴放在一起。编辑者可以边听边改文本、调整说话人、拆分或合并台词,并微调时间位置,而不必在多个中间文件之间寻找对应关系。
上图保留早期版本的操作界面,用于说明校准方式;图中的旧阶段名称和导出方式不代表本文数据库版本的数据协议。
在数据库版本中,编辑通过应用写回字幕记录。下游读取这些记录进行翻译和合成;导出的 SRT 用于查看或交付,不再承担另一份可独立编辑的权威数据。
三、翻译必须带着画面给定的时间预算
台词翻译既要保留含义,又要能在镜头内说完。中文“坐牢十年”是 4 个汉字,英文“Ten years in prison”是 4 个词,两者的朗读时长不能靠字符或词数直接换算。
Translate 读取原文台词组及其字幕条目,结合故事背景、人物名称和命中的术语进行翻译。多条字幕合为一个台词组时,使用编号约束输出,再逐条回填译文,避免只得到一段无法对应回原字幕的文本。
3.1 术语要在相关语境里出现
原稿记录过一次具体问题:全局注入带有强制措辞的赌博术语表后,无关台词也被翻成了牌桌用语。调整为按当前台词匹配术语,并采用有条件的领域提示,减少了这种干扰。
关键词命中只是缩小候选范围,不能证明词义已经确定。例如“三条”究竟指牌、物品还是数量,仍依赖上下文。术语表解决的是可控提示和名称一致性,译文审核还要检查含义。
字幕的行宽、行数和阅读速度也应作为目标平台的配置。原方案采用每行不超过 42 字符、最多两行、12–17 CPS 的编辑目标;这些是项目约束,不是适用于所有语言和终端的统一标准。
3.2 区分原时间窗与允许使用的额外间隙
原始时间窗由 start_ms 和 end_ms 决定,基本预算为:
budget_ms = end_ms - start_ms
TTS 先尝试在预算内完成,必要时裁去头尾静音或做有限变速。项目默认最大倍率为 1.3,超出可适配范围的片段需要缩短译文或重新审核,不能靠无限加速解决。
实现还提供 allow_extend_ms,允许使用额外时间。因此准确的设计目标是:保持源台词时间锚点,并显式管理配音延长量,不是“所有片段绝不延长”。3 月版本会参考后续间隙计算额度,同时有短句补偿规则;仅凭这一计算不能保证所有延长都不侵占下一句。发布前需要检查最终音频的实际结束位置、后续对白和视频尾部,冲突片段返回修改。
早期把片段直接拼接的方案曾让原有停顿丢失,原稿也记录了音轨超过视频时长的问题。应避免的是未经整体检查就累计推后台词。人工校准可以修改时间轴,但修改后要重新审核相应的字幕和音频。
四、角色声线与逐段合成
4.1 从“这是谁”到“使用哪种声音”
项目使用 VolcEngine TTS 合成逐段 WAV。进入 TTS 前先读取整剧角色的音色配置,检查台词涉及的角色是否已分配音色;缺失时返回可定位的错误,让编辑者补齐。
数据库版本的音色配置保存在 roles 表中。早期 roles.json 和按 gender 兜底的设计不应继续作为当前操作说明。声线是否适合角色,需要结合语言、情绪表达和试听判断,不能只靠识别出的性别标签。
这是早期 Voice Casting 界面:角色选择、音色绑定和试听的工作方式延续下来,底层配置已从文件迁入数据库。
试听减少的是配置与听感之间的距离:先选择角色,再用该角色的实际台词比较声音,确认后将同一配置用于相关集数。普通声线选择和声音克隆是两条不同路径;接入参考音频并不会自动解决说话人归属、跨集身份和授权问题。
4.2 一句失败,不必抹掉其他句子的结果
每个 utterance 单独生成音频,并记录原始时长、处理后时长、变速倍率和错误。短于预算时可以补静音,超过预算时尝试去除静音或有限变速;仍无法放入允许窗口的片段报告失败,交给编辑者处理。
音色、语言和情绪能力还受模型与具体声线限制。不能把统一的 emotion 字段直接当作所有供应商都支持的控制接口,需要在适配层校验或转换。
4.3 增量执行分为两层
阶段层决定任务是否需要运行,台词层决定哪些条目需要翻译或重新合成。
3 月版本的 Runner 检查任务记录、Phase 版本、输入输出文件存在性和完成状态;Translate 和 TTS 再根据条目指纹筛选待处理数据。这里已经不是早期文件版的“七级内容指纹检查”,也不再使用手工修改 JSON 后执行 bless 的操作方式。
| 层次 | 本版检查依据 | 解决的问题 |
|---|---|---|
| 阶段 | 任务状态、版本、必要文件 | 是否进入该阶段 |
| 翻译条目 | 源字幕内容指纹、译文是否缺失 | 哪些台词需要翻译 |
| 合成条目 | 英文文本、speaker、emotion 的指纹 | 哪些台词被标记为需要重新合成 |
| 音频文件缓存 | 合成器实际使用的缓存键 | 能否复用已经生成的音频 |
这些机制降低了改一句台词就重算整集的成本,但指纹覆盖范围必须与配置保持一致。例如角色仍是同一个 ID,却换了音色,不能仅凭文本和 speaker 不变就认为原音频仍可用。版本切换、音色调整和渲染策略变化,都要配套失效处理,不能把“使用了哈希”写成“任何修改都自动正确重算”。
五、混音按时间轴放置,再检查成片
5.1 保留每句台词的开始位置
逐段合成之后,Mix 使用 FFmpeg 的 adelay 将音频放回指定开始位置,再与伴奏混合。下面是滤镜片段的构造示例,idx 和 start_ms 由台词记录提供:
f"[{idx}:a]volume=1.4,adelay={start_ms}|{start_ms}[seg_{idx}]"
FFmpeg 的 adelay 文档说明了各声道延迟的含义。上例为两个声道设置相同延迟;实际构造时应与输入声道数量一致。它保留台词间的空隙,避免将所有语音无缝拼接后再全局拉伸。
伴奏可以通过侧链压缩在对白出现时降低音量,再平滑恢复。压缩阈值、释放时间和对白增益依赖素材,不是一组参数就能适配所有剧集。
5.2 长度对齐不能替代对白完整性检查
apad 可以补足尾部静音,atrim 可以限制输出长度。但最后一刀截到视频时长,并不能证明最后一句话完整。合成记录应先确认每段实际结束位置,再检查混音中的残留原声、重叠对白和尾句。
原稿采用 -16 LUFS、True Peak -1 dB 的目标,可作为该项目的混音设置;交付时仍以目标平台要求为准,不能称为统一的“短视频标准”。
5.3 烧字幕是交付步骤,擦除旧字幕是另一个任务
在视频、混音和英文 SRT 准备好后,可以使用以下命令合成新文件。示例要求 FFmpeg 带有 subtitles 滤镜,并在当前目录准备好输入文件:
ffmpeg -i video.mp4 -i mix.wav \
-vf "subtitles=en.srt" \
-c:v libx264 -c:a aac \
-map 0:v:0 -map 1:a:0 \
output.mp4
如果原片已经烧录中文字幕,直接叠加英文可能遮挡。字幕擦除在本文版本中尚未接入正式流水线,不能算作第八个已实现阶段。
一种后续方案是先用 OCR 生成逐帧区域,再通过 ProPainter 等视频修复方法处理。OCR 搜索范围应随字幕位置调整,不能只检查画面底部固定比例;遮罩扩展也要考虑分辨率。修复后的文字残影、人物边缘和帧间闪烁,都应在真实素材上检查,不能根据单帧效果宣称已经满足成片质量。
六、系统如何支持人修改,而不是逼人重来
这套系统保留 Phase 与 Processor 的分工:Phase 负责阶段编排、任务上下文和产物记录,Processor 承担音频、字幕或模型处理。Processor 中可能存在文件操作、子进程或服务调用,所以“无状态业务处理”不等于“纯函数、无 I/O”。
这种分层的价值,在于可以单独定位识别、翻译、合成和混音问题。文件写入的完整性、数据库更新和失败恢复,则需要各自的提交逻辑,不能由分层名称自动保证。
排查一条失败配音时,沿着下面的记录即可缩小范围:
| 记录 | 要回答的问题 |
|---|---|
| ASR 原始响应 | 错误是否已出现在识别阶段? |
| 数据库字幕与台词组 | 人工修改是否进入下游,台词如何分组? |
| 译文与时间策略 | 含义是否正确,预算是否合理? |
| 逐段 TTS 报告 | 哪一句失败、变速多少、实际时长多少? |
| 混音与字幕产物 | 放置位置与最终听感是否一致? |
| 任务与产物记录 | 本次运行了哪些阶段,使用了哪些结果? |
人工审核也因此有了具体对象:校准处理原文与角色,翻译审核处理目标语言,成片检查处理最终视听结果。通过前一个 Gate 不代表后续所有质量问题都已被排除。
七、成本收益要按正确口径计算
原稿记录的单集 2–5 分钟素材,ASR、翻译和 TTS 的 API 支出约为 ¥0.3–0.5;另记录过从输入到输出约 10–15 分钟的处理观察。这些是作者在项目当时条件下的记录,不是服务商现行报价,也不是覆盖全部素材的性能基准。
API 支出没有包含本地计算、存储、人工审核、返工与声线授权;处理时间也缺少统一硬件、并发与审核耗时口径,不能直接作为生产交付承诺。要评估量产收益,应按“通过审核的成片分钟数”归集上述成本,同时记录首次通过率和返工原因。
增量执行的价值则更直接:译文只改一句,系统能将重新翻译、合成和审核范围缩到相关台词;角色配置按剧共享,减少逐集重复绑定;中间产物可追溯,缩短错误定位时间。这些可观察的工作量变化,比没有条件说明的单集低价更能解释自动化的收益。
下一步是否增加多语言、声音克隆或口型同步,也应沿着同一原则推进:保留可审核的文本和时间锚点,为新的模型产物增加版本、缓存和检查入口。配音模型可以更换,明确的数据归属、可定位的失败和受控的局部重算,才是这条流水线能够持续演进的基础。

