feat: Ausschnitte an Satzgrenzen erweitern (--exakt schneidet genau)
Bei -s/-e werden angeschnittene Sätze an beiden Enden vollständig aufgenommen (höchstens 30 s über den Zeitraum hinaus). rede_korrigieren.py weist das Modell bei Ausschnitten zusätzlich an, nichts zu ergänzen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9bbf325bd3
commit
faea4bf465
1 changed files with 234 additions and 28 deletions
|
|
@ -188,17 +188,17 @@ def test_time_suffix(start, end, suffix):
|
|||
assert vtt2txt.time_suffix(start, end) == suffix
|
||||
|
||||
|
||||
def test_vtt_to_lines_time_range():
|
||||
def test_vtt_to_lines_exact_time_range():
|
||||
vtt = "WEBVTT\n\n" + cue(1, "A") + cue(2, "A", "B") + cue(3, "B", "C") + cue(4, "C", "D")
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=2, end=4) == ["B", "C"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=3) == ["C", "D"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, end=2) == ["A"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=2, end=4, exact=True) == ["B", "C"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=3, exact=True) == ["C", "D"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, end=2, exact=True) == ["A"]
|
||||
|
||||
|
||||
def test_vtt_to_lines_time_range_skips_window_from_before_start():
|
||||
# "B" was said before the range; its repetition in the first cue must not count
|
||||
vtt = "WEBVTT\n\n" + cue(1, "A", "B") + cue(2, "B", "C")
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=2) == ["C"]
|
||||
assert vtt2txt.vtt_to_lines(vtt, start=2, exact=True) == ["C"]
|
||||
|
||||
|
||||
def test_main_time_range_default_name(sample_copy, monkeypatch):
|
||||
|
|
@ -225,3 +225,70 @@ def test_cli_time_errors(sample_copy, monkeypatch, capsys, args, message):
|
|||
run_main(monkeypatch, "-i", sample_copy, *args)
|
||||
assert exc.value.code == 2
|
||||
assert message in capsys.readouterr().err
|
||||
|
||||
|
||||
def timed_cue(seconds, *lines):
|
||||
return f"{vtt2txt.format_time(seconds)}.000 --> {vtt2txt.format_time(seconds + 1)}.000\n" \
|
||||
+ "\n".join(lines) + "\n\n"
|
||||
|
||||
|
||||
def captions(*cues):
|
||||
"""VTT with one new line per cue: cues are (seconds, text)."""
|
||||
return "WEBVTT\n\n" + "".join(timed_cue(t, text) for t, text in cues)
|
||||
|
||||
|
||||
SPEECH = captions(
|
||||
(100, "Erster Satz ist hier."), (102, "Der zweite Satz"), (104, "beginnt vorher. Dann"),
|
||||
(106, "kommt der dritte"), (108, "und endet. Der vierte"), (110, "läuft weiter"),
|
||||
(112, "und endet auch. Schluss"), (114, "folgt."),
|
||||
)
|
||||
|
||||
|
||||
def test_snap_extends_both_sides_to_sentences():
|
||||
# Range holds only "kommt der dritte" and "und endet. Der vierte"
|
||||
assert vtt2txt.vtt_to_lines(SPEECH, start=106, end=110) == [
|
||||
"Dann", "kommt der dritte", "und endet. Der vierte", "läuft weiter",
|
||||
"und endet auch.",
|
||||
]
|
||||
|
||||
|
||||
def test_snap_keeps_range_already_at_sentence_bounds():
|
||||
assert vtt2txt.vtt_to_lines(SPEECH, start=102, end=104) == [
|
||||
"Der zweite Satz", "beginnt vorher.",
|
||||
]
|
||||
assert vtt2txt.vtt_to_lines(SPEECH, start=100, end=102) == ["Erster Satz ist hier."]
|
||||
|
||||
|
||||
def test_snap_reaches_start_and_end_of_captions():
|
||||
assert vtt2txt.vtt_to_lines(SPEECH, start=114) == ["Schluss", "folgt."]
|
||||
speech = captions((0, "ohne Satzzeichen"), (2, "am Anfang. Rest"))
|
||||
assert vtt2txt.vtt_to_lines(speech, start=2) == ["ohne Satzzeichen", "am Anfang. Rest"]
|
||||
|
||||
|
||||
def test_snap_cuts_exactly_without_sentence_end_in_reach():
|
||||
far = vtt2txt.MAX_SNAP_SECONDS + 5
|
||||
speech = captions(
|
||||
(0, "Satz."), (2, "ein endloser"), (far, "Satz ohne"), (2 * far, "Ende"), (3 * far, "jetzt."),
|
||||
)
|
||||
assert vtt2txt.vtt_to_lines(speech, start=far, end=far + 1) == ["Satz ohne"]
|
||||
|
||||
|
||||
def test_snap_exact_keeps_cut():
|
||||
assert vtt2txt.vtt_to_lines(SPEECH, start=106, end=110, exact=True) == [
|
||||
"kommt der dritte", "und endet. Der vierte",
|
||||
]
|
||||
|
||||
|
||||
def test_snap_closing_quote_belongs_to_sentence():
|
||||
speech = captions((0, "Er sagte „Nein.“ Und"), (2, "dann"), (4, "ging er."))
|
||||
assert vtt2txt.vtt_to_lines(speech, start=2, end=4) == ["Und", "dann", "ging er."]
|
||||
|
||||
|
||||
def test_main_exact_option(tmp_path, monkeypatch):
|
||||
source = tmp_path / "rede.vtt"
|
||||
source.write_text(SPEECH, encoding="utf-8")
|
||||
run_main(monkeypatch, "-i", source, "-s", "106", "-e", "110", "--exakt")
|
||||
target = tmp_path / "rede_00-01-46_bis_00-01-50.txt"
|
||||
assert target.read_text(encoding="utf-8") == "kommt der dritte\nund endet. Der vierte\n"
|
||||
run_main(monkeypatch, "-i", source, "-s", "106", "-e", "110")
|
||||
assert target.read_text(encoding="utf-8").endswith("und endet auch.\n")
|
||||
|
|
|
|||
Loading…
Reference in a new issue