feat: Zeitraum-Auswahl (-s/-e) auch in rede_korrigieren.py und extract_text.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1668a8dcad
commit
82489ee83c
5 changed files with 111 additions and 17 deletions
10
README.md
10
README.md
|
|
@ -66,6 +66,7 @@ Zwischenschritt im temporären Verzeichnis. Die Spurwahl ist dieselbe wie bei
|
||||||
# → John_Mearsheimer_Offensive_Realism_Episode_1_Origins_of_the_War_In_Ukraine_2026-07-30.txt
|
# → John_Mearsheimer_Offensive_Realism_Episode_1_Origins_of_the_War_In_Ukraine_2026-07-30.txt
|
||||||
./extract_text.py -u URL -l de -o testdaten/rede.txt # Sprache und Ziel
|
./extract_text.py -u URL -l de -o testdaten/rede.txt # Sprache und Ziel
|
||||||
./extract_text.py -u URL -f -o rede.txt # lesbarer Fließtext
|
./extract_text.py -u URL -f -o rede.txt # lesbarer Fließtext
|
||||||
|
./extract_text.py -u URL -s 3:17 -e 5:25 # nur ein Ausschnitt
|
||||||
./rede_korrigieren.py -i rede.txt # → rede.korrigiert.txt
|
./rede_korrigieren.py -i rede.txt # → rede.korrigiert.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -74,6 +75,7 @@ Zwischenschritt im temporären Verzeichnis. Die Spurwahl ist dieselbe wie bei
|
||||||
| `-u`, `--url` | YouTube-URL, Pflicht |
|
| `-u`, `--url` | YouTube-URL, Pflicht |
|
||||||
| `-l`, `--lang` | Sprache; Standard: Sprache des Original-Audios (`<sprache>-orig`) |
|
| `-l`, `--lang` | Sprache; Standard: Sprache des Original-Audios (`<sprache>-orig`) |
|
||||||
| `-o`, `--output` | Ausgabedatei (Verzeichnisse werden angelegt, vorhandene Datei überschrieben); Standard: `<Kanal>_<Titel>_<Datum>.txt`, siehe unten |
|
| `-o`, `--output` | Ausgabedatei (Verzeichnisse werden angelegt, vorhandene Datei überschrieben); Standard: `<Kanal>_<Titel>_<Datum>.txt`, siehe unten |
|
||||||
|
| `-s`, `--start` / `-e`, `--ende` | nur Untertitel in diesem Zeitraum (`00:03:17`, `3:17` oder `197` Sekunden), wie bei `vtt2txt.py` |
|
||||||
| `-f`, `--fliesstext` | Fließtext, auf 80 Zeichen umbrochen (Wörter werden nie getrennt), statt der kurzen Untertitelzeilen; beides versteht `rede_korrigieren.py` |
|
| `-f`, `--fliesstext` | Fließtext, auf 80 Zeichen umbrochen (Wörter werden nie getrennt), statt der kurzen Untertitelzeilen; beides versteht `rede_korrigieren.py` |
|
||||||
|
|
||||||
### Standard-Dateinamen für YouTube-Videos
|
### Standard-Dateinamen für YouTube-Videos
|
||||||
|
|
@ -89,7 +91,9 @@ Ohne `-o` bzw. `-n` bilden `extract_text.py`, `yt_untertitel.py` und
|
||||||
Wörter werden mit `_` verbunden. Bindestriche und Punkte im Wort bleiben
|
Wörter werden mit `_` verbunden. Bindestriche und Punkte im Wort bleiben
|
||||||
(„Krone-Schmalz“), andere Zeichen fallen weg. Der Kanal wird auf 40, der Titel auf
|
(„Krone-Schmalz“), andere Zeichen fallen weg. Der Kanal wird auf 40, der Titel auf
|
||||||
60 Zeichen an einer Wortgrenze gekürzt. Ohne verwertbaren Kanal und Titel gilt die
|
60 Zeichen an einer Wortgrenze gekürzt. Ohne verwertbaren Kanal und Titel gilt die
|
||||||
Video-ID. Gleiches Video ergibt immer denselben Namen; eine vorhandene Datei wird
|
Video-ID. Mit `-s`/`-e` kommt der Zeitraum dazu, z. B.
|
||||||
|
`…_2026-07-30_00-03-17_bis_00-05-25` (nur `-s`: `_ab_…`, nur `-e`: `_bis_…`).
|
||||||
|
Gleiches Video ergibt immer denselben Namen; eine vorhandene Datei wird
|
||||||
überschrieben (ein mit `-u` gespeicherter, abweichender Rohtext aber nie).
|
überschrieben (ein mit `-u` gespeicherter, abweichender Rohtext aber nie).
|
||||||
|
|
||||||
### Untertitel herunterladen: `yt_untertitel.py`
|
### Untertitel herunterladen: `yt_untertitel.py`
|
||||||
|
|
@ -161,6 +165,7 @@ werden trotzdem umgewandelt; der Exit-Code ist dann 1.
|
||||||
./rede_korrigieren.py -i rede.de.vtt # VTT direkt → rede.de.korrigiert.txt
|
./rede_korrigieren.py -i rede.de.vtt # VTT direkt → rede.de.korrigiert.txt
|
||||||
./rede_korrigieren.py -u URL # YouTube → <Kanal>_<Titel>_<Datum>.korrigiert.txt
|
./rede_korrigieren.py -u URL # YouTube → <Kanal>_<Titel>_<Datum>.korrigiert.txt
|
||||||
./rede_korrigieren.py -i speech.txt -l en # englische Rede
|
./rede_korrigieren.py -i speech.txt -l en # englische Rede
|
||||||
|
./rede_korrigieren.py -u URL -s 3:17 -e 5:25 # nur ein Ausschnitt des Videos
|
||||||
```
|
```
|
||||||
|
|
||||||
| Option | Bedeutung |
|
| Option | Bedeutung |
|
||||||
|
|
@ -168,7 +173,8 @@ werden trotzdem umgewandelt; der Exit-Code ist dann 1.
|
||||||
| `-i`, `--input` | Eingabedatei: Rohabschrift (`.txt`) oder Untertitel (`.vtt`, wird wie mit `vtt2txt.py` umgewandelt) |
|
| `-i`, `--input` | Eingabedatei: Rohabschrift (`.txt`) oder Untertitel (`.vtt`, wird wie mit `vtt2txt.py` umgewandelt) |
|
||||||
| `-u`, `--url` | statt `-i`: YouTube-URL; Untertitel wie bei `extract_text.py`. Der Rohtext wird neben der Ausgabe gespeichert (`rede.korrigiert.txt` → `rede.txt`, sonst `<Name>.roh.txt`), eine vorhandene, abweichende Datei aber nie überschrieben |
|
| `-u`, `--url` | statt `-i`: YouTube-URL; Untertitel wie bei `extract_text.py`. Der Rohtext wird neben der Ausgabe gespeichert (`rede.korrigiert.txt` → `rede.txt`, sonst `<Name>.roh.txt`), eine vorhandene, abweichende Datei aber nie überschrieben |
|
||||||
| `-l`, `--lang` | Sprache der Rede: `de` oder `en` (auch mit Region, z. B. `en-US`); wählt Prompts und Prüfmarke. Mit `-u` zugleich die Sprache der Untertitel. Standard: `de`, mit `-u` die Sprache des Original-Audios |
|
| `-l`, `--lang` | Sprache der Rede: `de` oder `en` (auch mit Region, z. B. `en-US`); wählt Prompts und Prüfmarke. Mit `-u` zugleich die Sprache der Untertitel. Standard: `de`, mit `-u` die Sprache des Original-Audios |
|
||||||
| `-o`, `--output` | Ausgabedatei; Standard: `<Eingabe ohne Endung>.korrigiert.txt` neben der Eingabe, mit `-u` `<Kanal>_<Titel>_<Datum>.korrigiert.txt` |
|
| `-o`, `--output` | Ausgabedatei; Standard: `<Eingabe ohne Endung>.korrigiert.txt` neben der Eingabe, mit `-u` `<Kanal>_<Titel>_<Datum>.korrigiert.txt`; mit `-s`/`-e` zusätzlich der Zeitraum im Namen |
|
||||||
|
| `-s`, `--start` / `-e`, `--ende` | nur diesen Zeitraum korrigieren (`00:03:17`, `3:17` oder `197` Sekunden); nur mit `.vtt`-Eingabe oder `-u`, da reiner Text keine Zeitstempel hat |
|
||||||
| `-g`, `--glossar` | Glossar mit festen Ersetzungen und Schreibweisen; mehrfach angeben zum Kombinieren (Ersetzungen in Reihenfolge der Angabe) |
|
| `-g`, `--glossar` | Glossar mit festen Ersetzungen und Schreibweisen; mehrfach angeben zum Kombinieren (Ersetzungen in Reihenfolge der Angabe) |
|
||||||
| `-m`, `--model` | Ollama-Modell; Standard: `qwen3:32b` (Konstante `MODEL`) |
|
| `-m`, `--model` | Ollama-Modell; Standard: `qwen3:32b` (Konstante `MODEL`) |
|
||||||
| `--kein-bericht` | keinen Änderungsbericht schreiben |
|
| `--kein-bericht` | keinen Änderungsbericht schreiben |
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from vtt2txt import vtt_to_lines
|
from vtt2txt import add_time_options, check_time_range, time_suffix, vtt_to_lines
|
||||||
from yt_untertitel import (
|
from yt_untertitel import (
|
||||||
YT_DLP, choose_track, default_name, download, fetch_info, no_track_message,
|
YT_DLP, choose_track, default_name, download, fetch_info, no_track_message,
|
||||||
original_language,
|
original_language,
|
||||||
|
|
@ -27,13 +27,16 @@ def parse_args():
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-o", "--output", type=Path,
|
"-o", "--output", type=Path,
|
||||||
help="Ausgabedatei (Standard: <Kanal>_<Titel>_<Datum>.txt)",
|
help="Ausgabedatei (Standard: <Kanal>_<Titel>_<Datum>.txt, "
|
||||||
|
"mit -s/-e zusätzlich der Zeitraum)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-f", "--fliesstext", action="store_true",
|
"-f", "--fliesstext", action="store_true",
|
||||||
help=f"Fließtext, auf {FLOW_WIDTH} Zeichen umbrochen, statt Untertitelzeilen",
|
help=f"Fließtext, auf {FLOW_WIDTH} Zeichen umbrochen, statt Untertitelzeilen",
|
||||||
)
|
)
|
||||||
|
add_time_options(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
check_time_range(parser, args)
|
||||||
|
|
||||||
if args.output is not None and args.output.is_dir():
|
if args.output is not None and args.output.is_dir():
|
||||||
parser.error(f"-o/--output ist ein Verzeichnis: {args.output}")
|
parser.error(f"-o/--output ist ein Verzeichnis: {args.output}")
|
||||||
|
|
@ -42,10 +45,11 @@ def parse_args():
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
def fetch_text(url, lang=None):
|
def fetch_text(url, lang=None, start=None, end=None):
|
||||||
"""Download the subtitles of a video; return (video info, text lines).
|
"""Download the subtitles of a video; return (video info, text lines).
|
||||||
|
|
||||||
Without `lang` the language of the original audio is used.
|
Without `lang` the language of the original audio is used. `start`/`end`
|
||||||
|
(seconds) keep only the captions of that time range.
|
||||||
"""
|
"""
|
||||||
info = fetch_info(url)
|
info = fetch_info(url)
|
||||||
print(f"Video: {info.get('title', '?')}")
|
print(f"Video: {info.get('title', '?')}")
|
||||||
|
|
@ -65,17 +69,20 @@ def fetch_text(url, lang=None):
|
||||||
vtt = Path(f"{target_base}.{track}.vtt")
|
vtt = Path(f"{target_base}.{track}.vtt")
|
||||||
if not vtt.is_file():
|
if not vtt.is_file():
|
||||||
raise SystemExit("yt-dlp hat keine Untertitel-Datei geschrieben.")
|
raise SystemExit("yt-dlp hat keine Untertitel-Datei geschrieben.")
|
||||||
lines = vtt_to_lines(vtt.read_text(encoding="utf-8-sig"))
|
lines = vtt_to_lines(vtt.read_text(encoding="utf-8-sig"), start, end)
|
||||||
|
|
||||||
if not lines:
|
if not lines:
|
||||||
raise SystemExit("Die Untertitel enthalten keinen Text.")
|
if start is None and end is None:
|
||||||
|
raise SystemExit("Die Untertitel enthalten keinen Text.")
|
||||||
|
raise SystemExit("Die Untertitel enthalten im gewählten Zeitraum keinen Text.")
|
||||||
return info, lines
|
return info, lines
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
info, lines = fetch_text(args.url, args.lang)
|
info, lines = fetch_text(args.url, args.lang, args.start, args.ende)
|
||||||
output = args.output or Path(f"{default_name(info)}.txt")
|
suffix = time_suffix(args.start, args.ende)
|
||||||
|
output = args.output or Path(f"{default_name(info)}{suffix}.txt")
|
||||||
|
|
||||||
if args.fliesstext:
|
if args.fliesstext:
|
||||||
# Never split words, not even at hyphens ("EU-Gipfel")
|
# Never split words, not even at hyphens ("EU-Gipfel")
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import urllib.request
|
||||||
|
|
||||||
from aenderungen import REVIEW_MARK, print_summary, report_path, write_report
|
from aenderungen import REVIEW_MARK, print_summary, report_path, write_report
|
||||||
from extract_text import fetch_text
|
from extract_text import fetch_text
|
||||||
from vtt2txt import vtt_to_lines
|
from vtt2txt import add_time_options, check_time_range, time_suffix, vtt_to_lines
|
||||||
from yt_untertitel import YT_DLP, base_language, default_name, original_language
|
from yt_untertitel import YT_DLP, base_language, default_name, original_language
|
||||||
|
|
||||||
MODEL = "qwen3:32b"
|
MODEL = "qwen3:32b"
|
||||||
|
|
@ -452,7 +452,8 @@ def parse_args():
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-o", "--output", type=Path,
|
"-o", "--output", type=Path,
|
||||||
help="Ausgabedatei (Standard: <Eingabe ohne Endung>.korrigiert.txt, "
|
help="Ausgabedatei (Standard: <Eingabe ohne Endung>.korrigiert.txt, "
|
||||||
"mit -u <Kanal>_<Titel>_<Datum>.korrigiert.txt)",
|
"mit -u <Kanal>_<Titel>_<Datum>.korrigiert.txt; mit -s/-e zusätzlich "
|
||||||
|
"der Zeitraum)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-g", "--glossar", type=Path, action="append", default=[],
|
"-g", "--glossar", type=Path, action="append", default=[],
|
||||||
|
|
@ -466,7 +467,10 @@ def parse_args():
|
||||||
"--kein-bericht", action="store_true",
|
"--kein-bericht", action="store_true",
|
||||||
help="keinen Änderungsbericht <Ausgabe>.aenderungen.html schreiben",
|
help="keinen Änderungsbericht <Ausgabe>.aenderungen.html schreiben",
|
||||||
)
|
)
|
||||||
|
add_time_options(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
check_time_range(parser, args)
|
||||||
|
timed = args.start is not None or args.ende is not None
|
||||||
|
|
||||||
for glossary in args.glossar:
|
for glossary in args.glossar:
|
||||||
if not glossary.is_file():
|
if not glossary.is_file():
|
||||||
|
|
@ -483,8 +487,11 @@ def parse_args():
|
||||||
|
|
||||||
if not args.input.is_file():
|
if not args.input.is_file():
|
||||||
parser.error(f"Eingabedatei nicht gefunden: {args.input}")
|
parser.error(f"Eingabedatei nicht gefunden: {args.input}")
|
||||||
|
if timed and args.input.suffix.lower() != ".vtt":
|
||||||
|
parser.error("-s/-e brauchen Zeitstempel: nur mit .vtt-Eingabe oder -u.")
|
||||||
if args.output is None:
|
if args.output is None:
|
||||||
args.output = args.input.with_name(f"{args.input.stem}.korrigiert.txt")
|
suffix = time_suffix(args.start, args.ende)
|
||||||
|
args.output = args.input.with_name(f"{args.input.stem}{suffix}.korrigiert.txt")
|
||||||
if args.output.resolve() == args.input.resolve():
|
if args.output.resolve() == args.input.resolve():
|
||||||
parser.error("Ausgabedatei darf nicht die Eingabedatei sein.")
|
parser.error("Ausgabedatei darf nicht die Eingabedatei sein.")
|
||||||
return args
|
return args
|
||||||
|
|
@ -510,20 +517,21 @@ def save_raw_text(path, raw):
|
||||||
def read_source(args):
|
def read_source(args):
|
||||||
"""Return the raw transcript, the output path and the language of the speech."""
|
"""Return the raw transcript, the output path and the language of the speech."""
|
||||||
if args.url is not None:
|
if args.url is not None:
|
||||||
info, lines = fetch_text(args.url, args.lang)
|
info, lines = fetch_text(args.url, args.lang, args.start, args.ende)
|
||||||
lang = base_language(args.lang or original_language(info) or DEFAULT_LANGUAGE)
|
lang = base_language(args.lang or original_language(info) or DEFAULT_LANGUAGE)
|
||||||
if lang not in PROMPTS:
|
if lang not in PROMPTS:
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
f"Die Rede ist auf „{lang}“; unterstützt: {', '.join(PROMPTS)} (-l)."
|
f"Die Rede ist auf „{lang}“; unterstützt: {', '.join(PROMPTS)} (-l)."
|
||||||
)
|
)
|
||||||
target = args.output or Path(f"{default_name(info)}.korrigiert.txt")
|
suffix = time_suffix(args.start, args.ende)
|
||||||
|
target = args.output or Path(f"{default_name(info)}{suffix}.korrigiert.txt")
|
||||||
raw = "\n".join(lines) + "\n"
|
raw = "\n".join(lines) + "\n"
|
||||||
save_raw_text(raw_text_path(target), raw)
|
save_raw_text(raw_text_path(target), raw)
|
||||||
return raw, target, lang
|
return raw, target, lang
|
||||||
|
|
||||||
raw = args.input.read_text(encoding="utf-8-sig")
|
raw = args.input.read_text(encoding="utf-8-sig")
|
||||||
if args.input.suffix.lower() == ".vtt":
|
if args.input.suffix.lower() == ".vtt":
|
||||||
raw = "\n".join(vtt_to_lines(raw))
|
raw = "\n".join(vtt_to_lines(raw, args.start, args.ende))
|
||||||
return raw, args.output, base_language(args.lang or DEFAULT_LANGUAGE)
|
return raw, args.output, base_language(args.lang or DEFAULT_LANGUAGE)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -560,7 +568,9 @@ def main():
|
||||||
chunks = split_chunks(text)
|
chunks = split_chunks(text)
|
||||||
|
|
||||||
if not chunks:
|
if not chunks:
|
||||||
raise SystemExit("Die Eingabedatei ist leer.")
|
if args.start is None and args.ende is None:
|
||||||
|
raise SystemExit("Die Eingabedatei ist leer.")
|
||||||
|
raise SystemExit("Die Eingabedatei enthält im gewählten Zeitraum keinen Text.")
|
||||||
|
|
||||||
parts_dir.mkdir(parents=True, exist_ok=True)
|
parts_dir.mkdir(parents=True, exist_ok=True)
|
||||||
results = []
|
results = []
|
||||||
|
|
|
||||||
|
|
@ -125,3 +125,25 @@ def test_cli_errors(tmp_path, monkeypatch, capsys, args, message):
|
||||||
run_main(monkeypatch, *args)
|
run_main(monkeypatch, *args)
|
||||||
assert exc.value.code == 2
|
assert exc.value.code == 2
|
||||||
assert message in capsys.readouterr().err
|
assert message in capsys.readouterr().err
|
||||||
|
|
||||||
|
|
||||||
|
def test_time_range_default_name(fake_yt_dlp, tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setattr(yt.subprocess, "run", fake_yt_dlp(GERMAN_VIDEO, vtt=VTT))
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
run_main(monkeypatch, "-u", URL, "-s", "2", "-e", "0:03")
|
||||||
|
|
||||||
|
name = "Kanal_Eine_Rede_2026-03-28_00-00-02_bis_00-00-03.txt"
|
||||||
|
assert (tmp_path / name).read_text(encoding="utf-8") == "Schön, dass Sie da sind.\n"
|
||||||
|
|
||||||
|
|
||||||
|
def test_time_range_without_text(fake_yt_dlp, tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setattr(yt.subprocess, "run", fake_yt_dlp(GERMAN_VIDEO, vtt=VTT))
|
||||||
|
with pytest.raises(SystemExit, match="im gewählten Zeitraum keinen Text"):
|
||||||
|
run_main(monkeypatch, "-u", URL, "-s", "1:00", "-o", tmp_path / "out.txt")
|
||||||
|
|
||||||
|
|
||||||
|
def test_time_range_order_error(monkeypatch, capsys):
|
||||||
|
with pytest.raises(SystemExit) as exc:
|
||||||
|
run_main(monkeypatch, "-u", URL, "-s", "2:00", "-e", "1:00")
|
||||||
|
assert exc.value.code == 2
|
||||||
|
assert "muss vor -e/--ende liegen" in capsys.readouterr().err
|
||||||
|
|
|
||||||
|
|
@ -517,3 +517,52 @@ def test_cli_errors(sample_copy, monkeypatch, capsys, args, message):
|
||||||
run_main(monkeypatch, *args)
|
run_main(monkeypatch, *args)
|
||||||
assert exc.value.code == 2
|
assert exc.value.code == 2
|
||||||
assert message in capsys.readouterr().err
|
assert message in capsys.readouterr().err
|
||||||
|
|
||||||
|
|
||||||
|
# === Time range (-s/-e) ===
|
||||||
|
|
||||||
|
def test_main_url_time_range_default_names(from_url, tmp_path, monkeypatch):
|
||||||
|
monkeypatch.chdir(tmp_path)
|
||||||
|
run_main(monkeypatch, "-u", URL, "-s", "0:02")
|
||||||
|
|
||||||
|
name = "Kanal_Rede_2026-03-28_ab_00-00-02"
|
||||||
|
raw = (tmp_path / f"{name}.txt").read_text(encoding="utf-8")
|
||||||
|
assert raw == "Das ist bekannt.\n"
|
||||||
|
assert (tmp_path / f"{name}.korrigiert.txt").is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_url_time_range_without_text(from_url, tmp_path, monkeypatch):
|
||||||
|
with pytest.raises(SystemExit, match="im gewählten Zeitraum keinen Text"):
|
||||||
|
run_main(monkeypatch, "-u", URL, "-s", "1:00", "-o", tmp_path / "x.korrigiert.txt")
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_vtt_time_range(tmp_path, monkeypatch):
|
||||||
|
vtt = tmp_path / "rede.de.vtt"
|
||||||
|
vtt.write_text(VTT, encoding="utf-8")
|
||||||
|
monkeypatch.setattr(rk, "correct_chunk", identity_correct)
|
||||||
|
monkeypatch.setattr(rk, "find_paragraph_starts", every_nth_start(5))
|
||||||
|
run_main(monkeypatch, "-i", vtt, "-e", "2")
|
||||||
|
|
||||||
|
result = tmp_path / "rede.de_bis_00-00-02.korrigiert.txt"
|
||||||
|
assert result.read_text(encoding="utf-8") == "Der Kremmel ist in Moskau.\n"
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_vtt_time_range_without_text(tmp_path, monkeypatch):
|
||||||
|
vtt = tmp_path / "rede.de.vtt"
|
||||||
|
vtt.write_text(VTT, encoding="utf-8")
|
||||||
|
monkeypatch.setattr(rk, "correct_chunk", no_model_calls)
|
||||||
|
with pytest.raises(SystemExit, match="im gewählten Zeitraum keinen Text"):
|
||||||
|
run_main(monkeypatch, "-i", vtt, "-s", "1:00")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("args, message", [
|
||||||
|
(["-i", "{sample}", "-s", "1:00"], "nur mit .vtt-Eingabe oder -u"),
|
||||||
|
(["-i", "{sample}", "-s", "x"], "ungültige Zeit"),
|
||||||
|
(["-i", "{sample}", "-s", "2:00", "-e", "1:00"], "muss vor -e/--ende liegen"),
|
||||||
|
])
|
||||||
|
def test_cli_time_errors(sample_copy, monkeypatch, capsys, args, message):
|
||||||
|
args = [a.format(sample=sample_copy) for a in args]
|
||||||
|
with pytest.raises(SystemExit) as exc:
|
||||||
|
run_main(monkeypatch, *args)
|
||||||
|
assert exc.value.code == 2
|
||||||
|
assert message in capsys.readouterr().err
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue