feat: 优化学习视频转写与字幕清洗

This commit is contained in:
2026-09-11 14:26:02 +08:00
parent a8fe133aa4
commit eba9163246
12 changed files with 552 additions and 28 deletions
+66 -3
View File
@@ -292,13 +292,13 @@ def test_resolve_incomplete_candidate_skipped(tmp_path) -> None:
empty = tmp_path / "empty"
empty.mkdir()
resolved = resolve_model_path({}, env={}, candidates=[empty])
assert resolved == "large-v3"
assert resolved == "large-v2"
def test_resolve_fallback_remote() -> None:
"""验证全部本地候选缺失时回退到远端 large-v3 作为最后兜底。"""
"""验证全部本地候选缺失时回退到远端 large-v2 作为最后兜底。"""
resolved = resolve_model_path({}, env={}, candidates=[])
assert resolved == "large-v3"
assert resolved == "large-v2"
def test_format_timestamp() -> None:
@@ -1497,5 +1497,68 @@ def test_whisper_decode_full_cleanup_jp_hallucination(tmp_path, monkeypatch) ->
assert all(t != "-" for t in text_lines)
def test_whisper_decode_full_filters_short_moan(tmp_path, monkeypatch) -> None:
"""decode_full=true 时纯呻吟碎片整条删除,真实短词保留(2026-09 决策)。"""
class MoanModel:
def __init__(self, *args, **kwargs):
pass
def transcribe(self, path, **kwargs):
# 混合:正常句 + 纯呻吟碎片 + 真实短词(都应保留)。
return (
[
FakeSegment(0, 2, "気持ちいい"), # 正常
FakeSegment(2, 3, "あ〜"), # 纯呻吟 → 删
FakeSegment(3, 4, "ん?"), # 纯呻吟 → 删
FakeSegment(4, 5, "そこ"), # 真实短词 → 保留
FakeSegment(5, 6, "やばい"), # 真实短词 → 保留
],
None,
)
monkeypatch.setitem(
sys.modules, "faster_whisper", types.SimpleNamespace(WhisperModel=lambda *a, **k: MoanModel())
)
_make_wav(tmp_path / "audio.wav", 5)
resp = whisper_invoke(
_whisper_request(tmp_path, params={"language": "ja", "decode_full": True})
)
assert resp.status == "completed"
content = Path(resp.outputs["srt_uri"]).read_text(encoding="utf-8")
# 纯呻吟碎片被整条删除;真实短词与正常句保留。
assert "あ〜" not in content
assert "ん?" not in content
assert "気持ちいい" in content
assert "そこ" in content
assert "やばい" in content
assert content.count("-->") == 3 # 5 段 - 2 段呻吟 = 3 条
def test_whisper_decode_full_short_moan_can_disable(tmp_path, monkeypatch) -> None:
"""short_moan_max_chars=0 时关闭短呻吟过滤,所有内容原样保留。"""
class MoanModel2:
def __init__(self, *args, **kwargs):
pass
def transcribe(self, path, **kwargs):
return ([FakeSegment(0, 1, "あ〜"), FakeSegment(1, 2, "そこ")], None)
monkeypatch.setitem(
sys.modules, "faster_whisper", types.SimpleNamespace(WhisperModel=lambda *a, **k: MoanModel2())
)
_make_wav(tmp_path / "audio.wav", 5)
resp = whisper_invoke(
_whisper_request(
tmp_path,
params={"language": "ja", "decode_full": True, "short_moan_max_chars": 0},
)
)
assert resp.status == "completed"
content = Path(resp.outputs["srt_uri"]).read_text(encoding="utf-8")
assert "あ〜" in content
assert "そこ" in content
assert content.count("-->") == 2