fix: whisper 重复伪影整条删除,避免翻译层空响应失败
whisper 在单个窗口内卡住重复时会把一个单元写满整条 cue(实测 30 秒整、重复 74–446 次,如 `チン`×111)。这类正文会让下游 LLM 跟着循环、把输出预算耗在思考上, 最终 `content` 返回空串并报 `translation alignment failed … Expecting value: line 1 column 1 (char 0)`;它也可能直接渲染成超长字幕行。 - `nodes/subtitle_cleanup.py` 新增 `remove_repetition_entries`:**纯模式判据、无字符 词表**——展示时长 ≥15s 且同一 1–6 字单元连续重复 ≥6 次且覆盖正文 ≥70% 的 cue 整条 删除;真实短促呻吟(`ぇ`×15、`ああああああ`)靠时长区分,零误删。 - `nodes/whisper.py` 在转写产出处应用该清洗(VAD 开关都生效,它与套话幻觉无关)。 - 真实数据验证:本地全部真实转写 3605 条 cue 只删 5 条 30 秒伪影;对照实验同批次 伪影截短后 5/5 成功、原样 1/5。
This commit is contained in:
@@ -543,3 +543,25 @@ def test_real_whisper_transcribes_real_speech(tmp_path: Path) -> None:
|
||||
starts = [e["start"] for e in entries]
|
||||
assert starts == sorted(starts)
|
||||
assert max(starts) <= 62.0
|
||||
|
||||
|
||||
def test_invoke_drops_repetition_artifact_in_decode_full(tmp_path: Path, monkeypatch) -> None:
|
||||
"""decode_full 下删除 30 秒重复伪影:它会带着翻译层一起进重复循环。
|
||||
|
||||
数据:假模型返回一段 30 秒窗口被同一单元填满的伪影 + 一条真实台词。
|
||||
过程:调用 invoke(decode_full=True)。
|
||||
验证:伪影整条删除、真实台词保留,产物里不再出现超长重复正文。
|
||||
"""
|
||||
artifact = "チン" * 111
|
||||
model = FakeModel([
|
||||
FakeSegment(0.0, 30.0, artifact),
|
||||
FakeSegment(30.0, 33.0, "そこ、だめ"),
|
||||
])
|
||||
_inject_model(monkeypatch, model)
|
||||
|
||||
response = invoke(_request(tmp_path, SPEECH_WAV, chunk_seconds=0, decode_full=True))
|
||||
|
||||
assert response.status == "completed", response.error
|
||||
content = Path(response.outputs["srt_uri"]).read_text(encoding="utf-8")
|
||||
assert artifact not in content
|
||||
assert "そこ、だめ" in content
|
||||
|
||||
Reference in New Issue
Block a user