[BUG] AI 分句会把原文翻译掉,双语模式下原文行显示译文
Before you report
- I have searched existing issues to avoid duplicates
- I have tried with the latest available version (or can reproduce on latest)
Current vs. Expected behavior
开启 AI 分句后,双语字幕的原文行显示的是译文,而译文行是对该译文的二次翻译 —— 于是屏幕上出现两段内容相同、措辞略有出入的目标语言文本。
根因: 分句 system prompt 的 rule 6 是 **No translation** - Keep the original language,
只有一行,夹在 8 条规则中间,是整个 prompt 里最弱的约束。轻量模型(实测 DeepSeek
deepseek-v4-flash)在这个任务上会系统性地违反它,把 t 字段连同分句一起翻译掉。
数据流上没有任何一层能拦住:
parseSimplifiedVttToFragments(utils/subtitles/processor/ai-segmentation.ts)不做任何 语言校验,只要能解析出 ≥1 条 cue 就接受。runAiSegmentSubtitles(entrypoints/background/ai-segmentation.ts)写 cache 的唯一闸门 同样是length === 0,于是被污染的原文进了db.aiSegmentationCache。translateSubtitles(utils/subtitles/processor/translator.ts)只写translation字段、...fragment原样保留text,所以污染无法在翻译阶段被覆盖或发现。- 渲染层
MainSubtitle读subtitle.text、TranslationSubtitle读subtitle.translation(entrypoints/subtitles.content/ui/subtitle-lines.tsx),两行来自同一个 fragment。
结果是译文行等于「把已经是目标语言的文本再翻一遍」,措辞与原文行略有出入 —— 这正是双语两行 看起来像「同一句话说了两遍」的原因。
预期行为: 分句结果的 text 必须保持源语言。分句不应改写文本内容,只应决定切分点。
实测证据
在页面上直接读取 read-frog 注入的 shadow DOM(#read-frog-subtitles-ui-host):
mainCount: 1 // .subtitles-main 在 DOM 中只有一个元素
trCount: 1 // .subtitles-translation 在 DOM 中只有一个元素
main[0].hasCJK: true // 原文行内容是中文
main[0].len: 375 // 单条 cue 375 字符
translation[0]: "翻译中" // 译文行仍处于 pending源视频为英文,字幕轨为 YouTube 英文自动字幕(scrolling-asr 格式),目标语言中文。
原文行本应是英文。
同一时间点分别用 temperature 1.3 与 0.3 复测,分句边界每次都不同(说明缓存正常 miss、确实 重新采样),但两次都出现原文被翻译。所以这不是采样噪声偶发,而是稳定复现。
To Reproduce
- 配置一个自定义 LLM provider(实测 DeepSeek
deepseek-v4-flash),分配给视频字幕。 - 开启 AI 分句,字幕显示模式设为双语(
displayMode: bilingual)。 - 播放一个带 word-level 自动字幕(
scrolling-asr格式)的英文 YouTube 视频,目标语言设为中文。 - 观察原文行 —— 显示的是中文而非英文。
触发前提是送进模型的字幕轨为词级。开启 AI 分句时
utils/subtitles/fetchers/youtube/index.ts:425会直接return parseStandardSubtitles(...), 绕过parseScrollingAsrSubtitles,把滚动 ASR 轨打散成词级碎片。实测同一视频同一份 timedtext: 开启时 6468 条(平均 4.4 字符),关闭时 375 条(平均 79.9 字符)。人工上传字幕的视频输入是 句级的,不容易触发。
Which area(s) are affected? (Select all that apply)
Other
Extension version (if applicable)
1.46.0
Provide environment information
- Extension channel/version: Chrome Web Store 1.46.0Additional context
短期缓解: 强化 rule 6。目前它只有一行且位置靠后,可以移到 Output 段落顶部,并在 Critical Example 里补一个「输入是英文、输出必须仍是英文」的正例。但 prompt 层约束对轻量模型的 遵守率有限,只能算缓解。
结构性修复: 让模型只返回句子边界在输入数组里的索引,文本由代码从原始 fragment 回查 拼接。这样模型在结构上就没有改写文本的机会,原文污染、时间戳畸形、片段重复三类问题一并消失。
兜底校验: 在 parseSimplifiedVttToFragments 之后、写 cache 之前,比对分句输出与输入
fragment 的文本覆盖度(例如归一化后的字符集合或 n-gram 重合率)。原文被整段翻译时重合率会
骤降,可以直接拒绝该结果并回退到 optimizeSubtitles 的规则分句。
相关:#2099(temperature 无法为分句独立设置)、#2100(超长 cue)。三者都指向同一个结构性 问题:模型被授权改写文本与时间戳,而管线不校验它的输出。
需要可以提 PR
Source: mengxi-ream/read-frog