[优化复盘] YouDub 翻译模块这一整天做了什么,哪些方向有效,哪些已经证伪
这一天的主战场其实不是 TTS,而是翻译模块。
原因很直接:配音模块后面已经可以换到更接近目标音色的方案,但成片里最明显的短板仍然是字幕翻译本身不够像 B 站成熟成品,尤其是:
- rolling caption 场景里,上一句会偷吃下一句的信息。
- 英文原字幕是碎片化的,中文一旦逐句硬翻,就会又长又别扭。
- 如果过度追求“补全句子”,就会把后面的 punchline、名词、动作提前泄露。
- 如果过度追求“保留碎片边界”,中文又会变得太碎,不像真的成片字幕。
所以这轮优化,我把重点从“修某一个视频”切到了“做一套可泛化的翻译评估和迭代框架”。
这一天具体做了什么
1. 先把基准体系搭起来,不再凭感觉调
我没有继续盯着单个视频一条条修,而是直接拿 C:\Users\1\bili_yt_export\bili_youtube_first100.csv 里的九十多个 B 站/Youtube 对照样本做基准。
对应做了两件事:
- 扩展了
scripts/benchmark_translation.py - 新增了
scripts/analyze_translation_artifact.py
前者负责批量跑翻译+切句+配音文案重写的完整链路,输出每个 case 的指标和中间产物。
后者负责把每个 case 拆开看,尤其是这几层:
source_rowsprepared_source_rowstranslated_rows_pre_splitpredicted_rowsreference_rows
这一步非常关键,因为后面很多问题不是后处理造成的,而是 LLM 在 translated_rows_pre_split 这一步就已经把后面的内容借过来了。
2. 核心问题定位清楚了:rolling-caption 借后文
这一天里最大的收获,不是某个指标突然暴涨,而是把主问题定位准了:
YouTube 自动字幕/官方字幕里大量是 rolling-caption 结构,很多行本来就是半句、残句、跨行延续句。
如果直接让模型“逐句自然翻译”,它会非常倾向于把未来一两行的信息借进当前行,导致中文看起来顺了,但时间轴上提前剧透。
这个问题在 zwIqbrD6JX4 和 o2V-JJpJH_I 这两个 hard case 上最明显。
3. 把 fragment_guard 提升为默认主线
基于上面的发现,我把 fragment_guard 做成默认开启。
它的核心思想不是“强行把中文写残”,而是明确限制模型:
- 当前 id 只能表达当前源行已经出现的语义。
- 如果源行明显是 rolling-caption 的未完成片段,宁可中文略微开放,也不要把未来内容提前补齐。
这是目前唯一已经稳定证明有效、并且我愿意放进主线默认值的改动。
目前确认有效的结果
主线配置
当前稳定主线大致是:
- provider:
openai_context - api base:
http://192.168.10.88:8317/v1 - model:
gpt-5.4-mini - prompt profile:
auto_hybrid - temperature:
0 - fewshot:
8 fragment_guard=on- 其余实验开关默认关闭
已确认提升的数据
fragment_guard 从局部实验到中样本,都是正收益:
- 4 case 对比:
52.432 -> 53.322 - 8 case 对比:
55.958 -> 56.058
当前 8 case 主线报告:
- composite:
56.058 - chrF:
0.3707 - char F1:
0.7729 - density MAE ratio:
0.4272
这说明至少当前主线已经比更早的版本更不容易把后文提前借过来,整体节奏也更接近 B 站成品字幕的分布。
这一天里哪些方向已经被我基本证伪
1. 全局开启 fragment_hints
它不是完全没用,反而在某些 case 上很强。
比如:
zwIqbrD6JX4在 hard2 里从54.439提到57.980VT6rLcVKhzg也有明显提升
但问题是它不稳定。
放到 8 case 上,整体反而从 56.058 掉到 55.296。
也就是说,它更像是“特定结构下的强药”,不是当前可以默认打开的主线策略。
2. auto_hybrid_v2
我做过一版更激进的 profile 自动选择逻辑,想让不同视频自动在 literal_context / bilibili_dub / bilibili_pacing 之间切。
结果 8 case 直接掉到 54.375,不如当前主线 56.058。
结论很简单:门控逻辑还不够准,现阶段不能上主线。
3. 强行放大全文翻译范围
我试过两个方向:
- 提高 full-context 阈值,让更多视频整篇一次性翻
- 把 chunk 从很小的窗口直接放大
看上去它更接近“整篇理解后再翻译”,但实际没有稳定增益。
原因是上下文更多以后,模型也更容易跨 id 借内容,时间轴反而可能更乱。
4. 把 chunk 颗粒度降得很细
例如 chunk_max_items=2 这种思路,直觉上像是在减少串句,但实际收益很差,速度还明显变慢。
hard2 的结果没有带来质量改进,延迟却大幅上涨,尤其 o2V-JJpJH_I 很拖。
5. 直接把“B 站风格提示词”拉满
我测试过:
literal_contextbilibili_dubbilibili_pacingauto_hybrid
在 mixed4 上,auto_hybrid 最好,literal_context 次之,另外两个偏“强风格”的 profile 反而更差。
这说明现在不是“提示词越像 B 站越好”,而是先得解决上下文边界、碎片句和 timing 对齐,再谈风格化表达。
这一天里最重要的认知变化
我原来以为最大问题是“句子翻得不够地道”,后来发现不对。
更底层的问题其实是:
- 先验输入本身就是碎的
- 碎片之间又高度重叠
- 中文要自然,就必须适度补语气和结构
- 但一旦补过头,就会提前泄露未来内容
所以翻译模块最难的地方,不是“中译英”或者“英译中”本身,而是:
在 不越过时间边界 的前提下,把碎英文整理成 像真正成片字幕那样的中文节奏。
这件事和普通机器翻译不是一个问题。
现在还没解决的点
虽然主线比之前稳了,但离我想要的目标还差得很远,尤其还没达到你给的 B 站案例那种完成度。
当前还明显没解决好的点:
- 某些 hard case 依然会借后文
- 某些 case 上中文仍然偏“翻译腔”
- 切句之后的长度匹配还不够稳
fragment_hints还没有找到稳定门控条件- few-shot 的数量和样本挑选还没有完全调到最优
下一步我认为最值得继续的方向
目前最值得继续追的,不是再加更多玄学 prompt,而是这三件事:
1. 做 fragment_hints 的特征门控,而不是全局开关
当前已经知道它会在某些 case 上强烈有效。
下一步应该根据这些特征做门控:
- fragmentary source ratio
- overlap ratio
- punctuated source ratio
- short/tiny line ratio
也就是只在“高碎片、高滚动字幕”的视频上启用,而不是全局一刀切。
2. 继续验证 few-shot 数量
今天最后出现的一个小信号是:fewshot=4 在 hard2 上第一次出现了小幅净增益:
- baseline hard2:
50.454 - fewshot=4 hard2:
50.600
这个增益不大,但方向是正的。
如果 mixed4 和 mid8 也能保持,就说明当前 8 个 few-shot 可能反而有点噪声过多。
3. 继续做“只给上下文,不给翻译权限”的 chunk context
我已经加了一版 chunk 前后文窗口,但目前只是实验态。
这个方向的价值在于:
- 给模型整段理解能力
- 同时仍然要求它只输出目标 chunk 的 id
这比单纯扩大 chunk,理论上更适合做“理解全文但不越界”的翻译。
这一天的结论
如果只用一句话总结:
这一天最大的成果不是把翻译模块做完了,而是把“这个问题为什么难、现在主瓶颈在哪、哪些方向有效、哪些方向已经不值得继续烧时间”这套认知打清楚了。
现在至少已经明确:
- 这个项目的翻译问题,本质上不是普通 MT
- rolling-caption 边界是主矛盾
fragment_guard是当前唯一稳定正收益fragment_hints有潜力,但必须门控- few-shot 和上下文策略还值得继续挖
如果后面要把这套工具真的打磨到“世界上最好的外语视频翻译配音”那个方向,翻译模块接下来就不能再靠拍脑袋调 prompt 了,必须继续沿着 基准驱动、case 归因、再小步 A/B 这条路往下走。
今天至少把这条路铺出来了。