test: eigene Beispielrede statt echter Reden, testdaten/ nur noch lokal
Die Abschriften echter Reden sind urheberrechtlich geschützt und gehören nicht in ein öffentliches Repository. Die Tests nutzen jetzt eine frei erfundene Festrede (tests/daten/beispiel.de.vtt/.txt, YouTube-Format mit rollendem Fenster) mit eigenem Glossar. testdaten/ steht in .gitignore; liegen die Reden dort lokal, laufen die Tests ihrer Glossare zusätzlich, sonst werden sie übersprungen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0106c307e7
commit
93fb99eda2
7 changed files with 3134 additions and 62 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -12,3 +12,6 @@ __pycache__/
|
||||||
|
|
||||||
# Eigene Ergebnisse und Testläufe
|
# Eigene Ergebnisse und Testläufe
|
||||||
output/
|
output/
|
||||||
|
|
||||||
|
# Echte Reden (Urheberrecht): nur lokal; die Tests nutzen tests/daten/
|
||||||
|
testdaten/
|
||||||
|
|
|
||||||
38
README.md
38
README.md
|
|
@ -415,24 +415,30 @@ werden in `<Entwurf>.parts/` zwischengespeichert.
|
||||||
|
|
||||||
## Testdaten
|
## Testdaten
|
||||||
|
|
||||||
`testdaten/` enthält drei Reden, jeweils als automatische YouTube-Untertitel
|
**Im Repository:** `tests/daten/` enthält eine frei erfundene Beispielrede
|
||||||
(`.vtt`, Original) und daraus mit `vtt2txt.py` gewonnener Rohtext (`.txt`, Eingabe
|
(Festrede zum Jubiläum der Gemeinde „Auental“; Ort und Personen gibt es nicht), als
|
||||||
für das Programm):
|
Untertitel im Format der YouTube-Auto-Untertitel (`beispiel.de.vtt`, rollendes
|
||||||
|
Fenster, Wort-Zeitstempel), daraus gewonnener Rohtext (`beispiel.de.txt`) und ein
|
||||||
|
passendes Glossar (`beispiel.glossar.txt`) für die eingebauten Hörfehler wie
|
||||||
|
„Auen Tal“ oder „Haber Kamp“. Die Tests nutzen nur diese Daten.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./abschrift_korrigieren.py -i tests/daten/beispiel.de.txt -g tests/daten/beispiel.glossar.txt -o /tmp/beispiel.korrigiert.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nur lokal:** Echte Reden gehören wegen des Urheberrechts nicht ins Repository;
|
||||||
|
`testdaten/` ist deshalb in `.gitignore`. Liegen dort die drei Reden, mit denen das
|
||||||
|
Programm entwickelt wurde, laufen zusätzlich die Tests, die ihre Glossare prüfen;
|
||||||
|
sonst werden diese übersprungen. Die Glossare dazu sind im Repository:
|
||||||
|
|
||||||
- `ramstein.de.*`: Rede über die US Air Base Ramstein (Glossar `ramstein.glossar.txt`)
|
- `ramstein.de.*`: Rede über die US Air Base Ramstein (Glossar `ramstein.glossar.txt`)
|
||||||
- `magdeburg.de-orig.*`: Rede in Magdeburg (Glossar `magdeburg.glossar.txt`)
|
- `magdeburg.de-orig.*`: Rede in Magdeburg (Glossar `magdeburg.glossar.txt`)
|
||||||
- `Lahnstein.de-orig.*`: Rede „Respekt geht anders“ in Lahnstein (Glossar
|
- `Lahnstein.de-orig.*`: Rede „Respekt geht anders“ in Lahnstein (Glossar
|
||||||
`lahnstein.glossar.txt`, erstellt mit Hilfe von `glossar_vorschlag.py`)
|
`lahnstein.glossar.txt`, erstellt mit Hilfe von `glossar_vorschlag.py`), zu laden mit
|
||||||
|
`./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d testdaten`
|
||||||
|
|
||||||
Alle drei mit dem gemeinsamen `krone-schmalz.glossar.txt` davor.
|
Alle drei mit dem gemeinsamen `krone-schmalz.glossar.txt` davor. Ein Lauf über eine
|
||||||
|
Rede dauert mit `qwen3:32b` vollständig auf einer RTX 3090 etwa 6–8 Minuten.
|
||||||
```bash
|
|
||||||
./vtt2txt.py -i "testdaten/*.vtt" # erzeugt alle .txt neu
|
|
||||||
./abschrift_korrigieren.py -i testdaten/ramstein.de.txt -g krone-schmalz.glossar.txt -g ramstein.glossar.txt
|
|
||||||
# → testdaten/ramstein.de.korrigiert.txt (nicht versioniert)
|
|
||||||
```
|
|
||||||
|
|
||||||
Ein Lauf dauert mit `qwen3:32b` vollständig auf einer RTX 3090 etwa 6 Minuten.
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
|
|
@ -440,7 +446,7 @@ Ein Lauf dauert mit `qwen3:32b` vollständig auf einer RTX 3090 etwa 6 Minuten.
|
||||||
python3 -m pytest
|
python3 -m pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Tests (323) brauchen weder Ollama noch Netz: Modellaufrufe und `yt-dlp` werden
|
Die Tests (325, ohne die lokalen Reden 318) brauchen weder Ollama noch Netz: Modellaufrufe und `yt-dlp` werden
|
||||||
durch Fakes ersetzt. `tests/test_abschrift_korrigieren.py` prüft Abschnittsbildung,
|
durch Fakes ersetzt. `tests/test_abschrift_korrigieren.py` prüft Abschnittsbildung,
|
||||||
Satzgrenzen (Abkürzungen und Ordnungszahlen sind kein Satzende), Glossar (inkl.
|
Satzgrenzen (Abkürzungen und Ordnungszahlen sind kein Satzende), Glossar (inkl.
|
||||||
„jede Ersetzung im Glossar einer Rede trifft diese Rede, jede im gemeinsamen Glossar
|
„jede Ersetzung im Glossar einer Rede trifft diese Rede, jede im gemeinsamen Glossar
|
||||||
|
|
@ -458,8 +464,8 @@ Die Tests nutzen eine kleine eigene Wortliste statt der des Systems.
|
||||||
(Original-Audio, manuell vor automatisch) und Fehlerfälle.
|
(Original-Audio, manuell vor automatisch) und Fehlerfälle.
|
||||||
`tests/test_yt_untertitel.py` prüft Spurauswahl, Aufruf von `yt-dlp` und
|
`tests/test_yt_untertitel.py` prüft Spurauswahl, Aufruf von `yt-dlp` und
|
||||||
Fehlerfälle (ohne Netz, `yt-dlp` wird durch Fakes ersetzt).
|
Fehlerfälle (ohne Netz, `yt-dlp` wird durch Fakes ersetzt).
|
||||||
`tests/test_vtt2txt.py` prüft die VTT-Umwandlung: jede `.vtt` in `testdaten/`
|
`tests/test_vtt2txt.py` prüft die VTT-Umwandlung: die Beispiel-`.vtt` (und lokal
|
||||||
ergibt genau die zugehörige `.txt`, echte Wiederholungen bleiben erhalten, auch bei
|
jede Rede in `testdaten/`) ergibt genau die zugehörige `.txt`, echte Wiederholungen bleiben erhalten, auch bei
|
||||||
Untertiteln ohne rollendes Fenster, dazu Zeitauswahl, Muster, Ausgabeverzeichnis und
|
Untertiteln ohne rollendes Fenster, dazu Zeitauswahl, Muster, Ausgabeverzeichnis und
|
||||||
Fehlerfälle.
|
Fehlerfälle.
|
||||||
|
|
||||||
|
|
|
||||||
335
tests/daten/beispiel.de.txt
Normal file
335
tests/daten/beispiel.de.txt
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
[applaus]
|
||||||
|
Vielen Dank. Liebe Gäste, liebe
|
||||||
|
Bürgerinnen und Bürger von Auen Tal, ich
|
||||||
|
freue mich sehr, dass Sie heute
|
||||||
|
so zahlreich gekommen sind. Wir feiern ein besonderes
|
||||||
|
Jubiläum. Vor 750 Jahren wurde unser
|
||||||
|
Ort zum ersten Mal
|
||||||
|
in einer Urkunde erwähnt. Das war im
|
||||||
|
Jahr 12 74. Damals war Auen
|
||||||
|
Tal ein kleiner Weiler mit
|
||||||
|
drei Höfen und einer Mühle am Bach.
|
||||||
|
Heute leben hier fast viertausend Menschen.
|
||||||
|
[applaus]
|
||||||
|
Ich möchte Ihnen heute keine lange Geschichtsstunde halten.
|
||||||
|
Dafür haben wir Frau Dr. Jorinde
|
||||||
|
Haber Kamp vom Kreisarchiv
|
||||||
|
eingeladen, die gleich noch zu Ihnen sprechen
|
||||||
|
wird. Ich möchte lieber erzählen, was
|
||||||
|
dieser Ort für uns bedeutet.
|
||||||
|
Und ich möchte erzählen, was wir in
|
||||||
|
den nächsten Jahren vorhaben.
|
||||||
|
Fangen wir mit der Mühle an. Die alte
|
||||||
|
Mühle am Linden Bach steht noch
|
||||||
|
heute. Sie hat viele
|
||||||
|
Besitzer gehabt. Sie ist zweimal abgebrannt und
|
||||||
|
zweimal wieder aufgebaut worden. Seit dem
|
||||||
|
3. Oktober 1990 gehört sie
|
||||||
|
der Gemeinde. Viele von Ihnen kennen sie
|
||||||
|
als Heimatmuseum. Manche kennen sie auch
|
||||||
|
als den Ort, an dem sie ihren ersten
|
||||||
|
Kuss bekommen haben. Ich nenne keine
|
||||||
|
Namen.
|
||||||
|
[lachen]
|
||||||
|
Die Mühle ist ein gutes Beispiel für
|
||||||
|
das, was Auen Tal ausmacht. Wir
|
||||||
|
bauen wieder auf, wenn etwas
|
||||||
|
kaputtgeht. Wir geben nicht auf. Und wir
|
||||||
|
machen das gemeinsam. Das klingt vielleicht
|
||||||
|
nach einer Floskel. Aber ich habe es selbst
|
||||||
|
erlebt. Als vor zwölf Jahren das
|
||||||
|
Hochwasser kam, standen am
|
||||||
|
nächsten Morgen über zweihundert Menschen mit Schaufeln
|
||||||
|
und Eimern vor dem Rathaus. Niemand
|
||||||
|
hatte sie gerufen. Sie waren
|
||||||
|
einfach da.
|
||||||
|
Ich erinnere mich an eine ältere
|
||||||
|
Dame aus der Bachstraße. Ihr Keller stand bis
|
||||||
|
zur Decke unter Wasser. Sie hat
|
||||||
|
trotzdem für alle Helfer
|
||||||
|
Kaffee gekocht. Sie hat gesagt, das Wasser
|
||||||
|
geht wieder, aber die Nachbarn bleiben.
|
||||||
|
Diesen Satz habe ich mir
|
||||||
|
gemerkt. Er hängt heute als Spruch in
|
||||||
|
meinem Büro.
|
||||||
|
Liebe Gäste, ein Jubiläum ist ein guter Anlass,
|
||||||
|
um zurückzuschauen. Es ist aber auch
|
||||||
|
ein guter Anlass, um
|
||||||
|
nach vorn zu schauen. Und da gibt
|
||||||
|
es einiges zu tun. Ich will
|
||||||
|
Ihnen drei Dinge nennen, die
|
||||||
|
uns in den nächsten Jahren beschäftigen werden.
|
||||||
|
Das erste ist die Schule. Unsere
|
||||||
|
Grundschule ist über hundert Jahre alt. Das Gebäude
|
||||||
|
ist schön, aber es ist zu
|
||||||
|
klein geworden. Wir haben
|
||||||
|
im letzten Jahr so viele Kinder eingeschult
|
||||||
|
wie seit Jahrzehnten nicht mehr. Das
|
||||||
|
ist eine gute Nachricht. Es
|
||||||
|
bedeutet aber auch, dass wir anbauen müssen.
|
||||||
|
Der Gemeinderat hat den Anbau im
|
||||||
|
Frühjahr beschlossen. Die Bauarbeiten beginnen im nächsten Sommer.
|
||||||
|
Wenn alles gut geht, ziehen die
|
||||||
|
Kinder in zwei Jahren
|
||||||
|
in die neuen Räume.
|
||||||
|
Das zweite ist der Verkehr. Viele
|
||||||
|
von Ihnen ärgern sich über
|
||||||
|
die Lastwagen, die durch die Hauptstraße fahren.
|
||||||
|
Ich ärgere mich auch. Seit Jahren
|
||||||
|
reden wir über eine Umgehungsstraße. Seit Jahren passiert
|
||||||
|
wenig. Ich will Ihnen nichts versprechen,
|
||||||
|
was ich nicht halten
|
||||||
|
kann. Aber ich kann Ihnen sagen, dass
|
||||||
|
das Land die Planung jetzt endlich
|
||||||
|
aufgenommen hat. Das ist ein
|
||||||
|
erster Schritt. Es werden noch viele Schritte
|
||||||
|
folgen müssen.
|
||||||
|
Das dritte ist die Nahversorgung. Seit der Bäcker
|
||||||
|
an der Kirche geschlossen hat, gibt
|
||||||
|
es im Ortskern kein
|
||||||
|
Geschäft mehr. Wer kein Auto hat, muss
|
||||||
|
mit dem Bus nach Linden Brunn
|
||||||
|
fahren. Das ist für viele
|
||||||
|
ältere Menschen ein Problem. Wir haben deshalb
|
||||||
|
mit einer Genossenschaft gesprochen, die Dorfläden
|
||||||
|
betreibt. Die Gespräche sind gut gelaufen. Ich hoffe,
|
||||||
|
dass wir Ihnen im Herbst mehr
|
||||||
|
dazu sagen können.
|
||||||
|
[applaus]
|
||||||
|
Ich weiß, dass das alles nicht spektakulär
|
||||||
|
klingt. Eine Schule, eine Straße, ein
|
||||||
|
Laden. Aber genau darum geht
|
||||||
|
es in einer Gemeinde wie unserer. Es
|
||||||
|
geht nicht um große Worte. Es
|
||||||
|
geht darum, dass das Leben hier gut funktioniert.
|
||||||
|
Für die Kinder, für die Familien,
|
||||||
|
für die Älteren.
|
||||||
|
Lassen Sie mich noch etwas zum Ehrenamt
|
||||||
|
sagen. Ohne die Vereine wäre Auen
|
||||||
|
Tal ein anderer Ort. Wir
|
||||||
|
haben einen Sportverein, einen Gesangverein, eine freiwillige
|
||||||
|
Feuerwehr, einen Heimatverein und einen Kleintierzuchtverein.
|
||||||
|
Wir haben eine Theatergruppe, die jedes Jahr im
|
||||||
|
Winter ein Stück aufführt. Und wir
|
||||||
|
haben seit drei Jahren
|
||||||
|
ein Repaircafé, in dem Menschen ihre kaputten
|
||||||
|
Toaster und Fahrräder reparieren lassen können.
|
||||||
|
Das alles funktioniert nur, weil
|
||||||
|
Menschen ihre freie Zeit hergeben. Sie tun
|
||||||
|
das ohne Bezahlung und oft ohne
|
||||||
|
Dank. Deshalb möchte ich heute ausdrücklich Danke sagen.
|
||||||
|
Danke an alle, die sich engagieren.
|
||||||
|
Sie sind das Herz
|
||||||
|
dieser Gemeinde.
|
||||||
|
[applaus]
|
||||||
|
Ein besonderer Dank geht an die
|
||||||
|
Freiwillige Feuerwehr. Sie feiert in
|
||||||
|
diesem Jahr ebenfalls ein Jubiläum, nämlich ihr
|
||||||
|
hundertfünfzigjähriges. Der Wehrführer Bernd Ols Hausen
|
||||||
|
hat mir erzählt, dass die erste Spritze noch
|
||||||
|
von Pferden gezogen wurde. Heute hat
|
||||||
|
die Wehr zwei moderne
|
||||||
|
Fahrzeuge. Aber eines ist gleich geblieben. Wenn
|
||||||
|
die Sirene geht, lassen die Frauen
|
||||||
|
und Männer alles stehen und
|
||||||
|
liegen und rücken aus. Das verdient unseren
|
||||||
|
Respekt.
|
||||||
|
Liebe Gäste, wir haben für das Jubiläumsjahr ein
|
||||||
|
Programm vorbereitet, das sich über den
|
||||||
|
ganzen Sommer zieht. Ich
|
||||||
|
will Ihnen nur einige Höhepunkte nennen. Im
|
||||||
|
Juni gibt es ein Mühlenfest mit
|
||||||
|
Führungen und einem Markt. Im
|
||||||
|
Juli zeigt die Theatergruppe ein Stück über
|
||||||
|
die Geschichte des Ortes. Im August
|
||||||
|
feiern wir ein Dorffest auf dem Anger mit
|
||||||
|
Musik und Tanz. Und im September
|
||||||
|
gibt es eine Ausstellung
|
||||||
|
im Rathaus mit alten Fotos aus Auen
|
||||||
|
Tal.
|
||||||
|
Für diese Ausstellung suchen wir
|
||||||
|
übrigens noch Bilder. Wenn Sie zu Hause
|
||||||
|
alte Fotos haben, z. B. von
|
||||||
|
Hochzeiten, von Festen oder einfach vom Alltag, dann
|
||||||
|
bringen Sie sie bitte ins Rathaus.
|
||||||
|
Wir scannen sie und
|
||||||
|
geben sie Ihnen sofort zurück. Frau Haber
|
||||||
|
Kamp hat mir versichert, dass solche
|
||||||
|
Bilder für das Archiv ein
|
||||||
|
großer Schatz sind.
|
||||||
|
Ich möchte auch etwas zu unseren
|
||||||
|
Partnern sagen. Seit über dreißig Jahren haben wir
|
||||||
|
eine Partnerschaft mit der Gemeinde Saint
|
||||||
|
Maur in Frankreich. Eine
|
||||||
|
Delegation aus Saint Maur ist heute hier.
|
||||||
|
Bienvenue, liebe Freunde. Wir freuen uns
|
||||||
|
sehr, dass Sie die weite
|
||||||
|
Reise auf sich genommen haben.
|
||||||
|
[applaus]
|
||||||
|
Die Partnerschaft hat mit einem Schüleraustausch
|
||||||
|
angefangen. Inzwischen gibt es Besuche der Vereine, der
|
||||||
|
Feuerwehren und der Chöre. Es gibt
|
||||||
|
sogar zwei Ehen, die
|
||||||
|
aus dieser Partnerschaft entstanden sind. Auch hier
|
||||||
|
nenne ich keine Namen.
|
||||||
|
Meine Damen und Herren, ich
|
||||||
|
habe vorhin gesagt, dass wir wieder aufbauen,
|
||||||
|
wenn etwas kaputtgeht. Das gilt nicht
|
||||||
|
nur für Gebäude. Es gilt auch für das
|
||||||
|
Miteinander. Auch bei uns gibt es
|
||||||
|
Streit. Es gibt Streit
|
||||||
|
über den Windpark, über die Parkplätze am
|
||||||
|
Friedhof und über die Frage, ob
|
||||||
|
der Weihnachtsbaum auf dem Marktplatz
|
||||||
|
echt sein muss oder aus Plastik sein
|
||||||
|
darf.
|
||||||
|
[lachen]
|
||||||
|
Streit gehört dazu. Aber wir sollten uns dabei
|
||||||
|
nicht aus den Augen verlieren. Wir
|
||||||
|
sollten miteinander reden und
|
||||||
|
nicht übereinander. Wir sollten zuhören, auch wenn
|
||||||
|
es schwerfällt. Das ist nicht immer
|
||||||
|
einfach. Ich schaffe das auch
|
||||||
|
nicht immer. Aber ich bemühe mich.
|
||||||
|
Lassen Sie mich zum Schluss noch
|
||||||
|
eine kleine Geschichte erzählen. Als ich vor sechs
|
||||||
|
Jahren zur Bürgermeisterin gewählt wurde, hat
|
||||||
|
mir mein Vorgänger einen
|
||||||
|
Schlüssel gegeben. Es war kein Schlüssel für
|
||||||
|
das Rathaus. Es war der Schlüssel
|
||||||
|
für den Kirchturm. Er hat
|
||||||
|
gesagt, wenn du einmal nicht weiterweißt, dann
|
||||||
|
steig da hoch und schau dir
|
||||||
|
den Ort von oben an.
|
||||||
|
Ich habe das ein paar Mal
|
||||||
|
gemacht. Von oben sieht
|
||||||
|
man die Dächer, die Gärten, den Bach
|
||||||
|
und die Mühle. Man sieht die
|
||||||
|
Felder und den Wald. Man
|
||||||
|
sieht, wie klein der Ort ist und
|
||||||
|
wie viel trotzdem darin steckt. Und
|
||||||
|
man merkt, dass die meisten Probleme von dort
|
||||||
|
oben ein bisschen kleiner aussehen.
|
||||||
|
Ich möchte, dass dieser
|
||||||
|
Ort auch in fünfzig Jahren noch ein
|
||||||
|
Ort ist, an dem man gern
|
||||||
|
lebt. Ein Ort, an dem
|
||||||
|
Kinder zur Schule laufen können. Ein Ort,
|
||||||
|
an dem ältere Menschen nicht allein
|
||||||
|
sind. Ein Ort, an dem man sich kennt
|
||||||
|
und sich hilft. Daran arbeiten wir.
|
||||||
|
Und dafür brauchen wir
|
||||||
|
Sie alle.
|
||||||
|
Bevor ich jetzt das Wort an
|
||||||
|
Frau Dr. Haber Kamp übergebe,
|
||||||
|
möchte ich noch einigen Menschen danken. Ich
|
||||||
|
danke dem Festausschuss, der seit über
|
||||||
|
einem Jahr dieses Jubiläum vorbereitet. Ich danke dem
|
||||||
|
Bauhof, der den Platz so schön
|
||||||
|
hergerichtet hat. Ich danke
|
||||||
|
dem Gesangverein für die Musik. Und ich
|
||||||
|
danke den Landfrauen für den Kuchen,
|
||||||
|
den Sie nachher alle probieren
|
||||||
|
sollten.
|
||||||
|
[lachen]
|
||||||
|
Ich wünsche uns allen ein schönes
|
||||||
|
Fest und ein gutes Jubiläumsjahr. Auf die nächsten
|
||||||
|
750 Jahre. Vielen Dank.
|
||||||
|
[applaus]
|
||||||
|
Ja, vielen Dank, Frau
|
||||||
|
Bürgermeisterin. Liebe Gäste, ich bin Jorinde Haber
|
||||||
|
Kamp und leite das Kreisarchiv. Ich
|
||||||
|
darf Ihnen heute ein wenig
|
||||||
|
über die Geschichte von Auen Tal erzählen.
|
||||||
|
Keine Sorge, ich halte mich kurz.
|
||||||
|
Die Urkunde aus dem Jahr 12 74 liegt
|
||||||
|
bei uns im Archiv. Sie ist
|
||||||
|
auf Pergament geschrieben, in
|
||||||
|
lateinischer Sprache, und sie ist erstaunlich gut
|
||||||
|
erhalten. Es geht darin um einen
|
||||||
|
Streit über Wasserrechte. Zwei Klöster
|
||||||
|
stritten sich darüber, wer die Mühle am
|
||||||
|
Bach nutzen darf. Der Ort selbst
|
||||||
|
wird nur nebenbei erwähnt. Aber er wird erwähnt,
|
||||||
|
und deshalb feiern wir heute.
|
||||||
|
Was wissen wir über
|
||||||
|
die Menschen, die damals hier gelebt haben?
|
||||||
|
Leider nicht viel. Sie konnten nicht
|
||||||
|
schreiben, und so haben sie
|
||||||
|
uns keine Briefe oder Tagebücher hinterlassen. Was
|
||||||
|
wir wissen, stammt aus Abgaberegistern, aus
|
||||||
|
Gerichtsakten und aus Kirchenbüchern. Daraus können wir aber
|
||||||
|
erstaunlich viel ablesen.
|
||||||
|
Wir wissen z. B.,
|
||||||
|
dass im Jahr 1580 in Auen Tal
|
||||||
|
elf Familien lebten. Wir wissen, dass
|
||||||
|
sie vor allem Roggen und
|
||||||
|
Hafer anbauten. Wir wissen, dass es im
|
||||||
|
Jahr 1636 eine schwere Pest gab,
|
||||||
|
an der fast die Hälfte der Menschen starb.
|
||||||
|
Und wir wissen, dass der Ort
|
||||||
|
sich danach nur langsam
|
||||||
|
erholt hat.
|
||||||
|
Ein besonderer Fund ist ein Gerichtsprotokoll
|
||||||
|
aus dem Jahr 1712. Darin
|
||||||
|
klagt ein Müller namens Kaspar Ols Hausen
|
||||||
|
gegen seinen Nachbarn, weil dessen Ziegen
|
||||||
|
immer wieder in seinen Garten eingedrungen seien. Das
|
||||||
|
Gericht gab dem Müller recht. Der
|
||||||
|
Nachbar musste einen Zaun
|
||||||
|
bauen und zwei Hühner als Entschädigung zahlen.
|
||||||
|
[lachen]
|
||||||
|
Ich erzähle Ihnen das nicht nur,
|
||||||
|
weil es lustig ist. Ich
|
||||||
|
erzähle es, weil es zeigt, dass die
|
||||||
|
Menschen damals ganz ähnliche Sorgen hatten
|
||||||
|
wie wir heute. Es ging um den Garten,
|
||||||
|
um den Nachbarn, um ein bisschen
|
||||||
|
Gerechtigkeit. Der Name Ols
|
||||||
|
Hausen ist übrigens bis heute im Ort
|
||||||
|
zu finden. Vielleicht ist der Wehrführer
|
||||||
|
ja ein Nachfahre des Müllers.
|
||||||
|
Im neunzehnten Jahrhundert hat sich Auen Tal
|
||||||
|
stark verändert. Im Jahr 1868 wurde
|
||||||
|
die Bahnstrecke nach Linden Brunn gebaut. Plötzlich konnten
|
||||||
|
die Bauern ihre Waren in die
|
||||||
|
Stadt bringen. Es entstanden
|
||||||
|
eine Ziegelei und eine kleine Weberei. Die
|
||||||
|
Einwohnerzahl hat sich in wenigen Jahrzehnten
|
||||||
|
verdoppelt.
|
||||||
|
Das zwanzigste Jahrhundert war auch hier eine
|
||||||
|
Zeit der Brüche. Zwei Weltkriege haben
|
||||||
|
viele Familien getroffen. Auf dem Friedhof erinnert ein
|
||||||
|
Denkmal an die Gefallenen. Nach dem
|
||||||
|
2. Weltkrieg kamen viele
|
||||||
|
Vertriebene in den Ort. Sie mussten untergebracht
|
||||||
|
werden, oft in sehr engen Verhältnissen.
|
||||||
|
Für die Alteingesessenen war das
|
||||||
|
nicht leicht, und für die Neuen noch
|
||||||
|
weniger.
|
||||||
|
Aber auch hier hat sich gezeigt, was die
|
||||||
|
Bürgermeisterin vorhin beschrieben hat. Mit der
|
||||||
|
Zeit sind die Neuen
|
||||||
|
zu Nachbarn geworden. Sie haben Häuser gebaut,
|
||||||
|
Vereine gegründet und Familien gegründet. Heute
|
||||||
|
weiß kaum noch jemand, wessen
|
||||||
|
Großeltern damals gekommen sind und wessen Großeltern
|
||||||
|
schon immer hier waren.
|
||||||
|
Liebe Gäste, Archive sind keine staubigen Orte. Sie
|
||||||
|
sind das Gedächtnis einer Gemeinschaft. Und
|
||||||
|
dieses Gedächtnis lebt davon,
|
||||||
|
dass Menschen etwas hineingeben. Deshalb unterstütze ich
|
||||||
|
den Aufruf der Bürgermeisterin ausdrücklich. Bringen
|
||||||
|
Sie Ihre Fotos, Ihre Briefe,
|
||||||
|
Ihre Erinnerungen. Was heute alltäglich erscheint, ist
|
||||||
|
in hundert Jahren ein wertvolles Zeugnis.
|
||||||
|
Ich habe Ihnen eine kleine Auswahl mitgebracht. Im
|
||||||
|
Foyer des Rathauses hängen ab heute
|
||||||
|
Kopien der Urkunde und
|
||||||
|
einiger anderer Dokumente. Schauen Sie sie sich
|
||||||
|
gern an. Und wenn Sie Fragen
|
||||||
|
haben, sprechen Sie mich an.
|
||||||
|
Ich bin den ganzen Nachmittag hier.
|
||||||
|
Ich wünsche Ihnen ein schönes Fest.
|
||||||
|
Vielen Dank für Ihre Aufmerksamkeit.
|
||||||
|
[applaus]
|
||||||
2683
tests/daten/beispiel.de.vtt
Normal file
2683
tests/daten/beispiel.de.vtt
Normal file
File diff suppressed because it is too large
Load diff
14
tests/daten/beispiel.glossar.txt
Normal file
14
tests/daten/beispiel.glossar.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Glossar für die Beispielrede tests/daten/beispiel.de.* (frei erfunden,
|
||||||
|
# Gemeinde und Personen gibt es nicht). Jede Ersetzung trifft die Rede.
|
||||||
|
|
||||||
|
# --- Feste Ersetzungen ---
|
||||||
|
Auen Tal => Auental
|
||||||
|
Haber Kamp => Haberkamp
|
||||||
|
Linden Brunn => Lindenbrunn
|
||||||
|
Linden Bach => Lindenbach
|
||||||
|
Ols Hausen => Olshausen
|
||||||
|
12 74 => 1274
|
||||||
|
|
||||||
|
# --- Begriffe ---
|
||||||
|
Saint-Maur
|
||||||
|
Jorinde Haberkamp
|
||||||
|
|
@ -11,9 +11,11 @@ import pytest
|
||||||
import abschrift_korrigieren as ak
|
import abschrift_korrigieren as ak
|
||||||
|
|
||||||
REPO = Path(__file__).resolve().parent.parent
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
SAMPLE = REPO / "testdaten" / "ramstein.de.txt"
|
# Own, made-up sample speech; real speeches are only kept locally in testdaten/
|
||||||
GLOSSARY = REPO / "ramstein.glossar.txt"
|
SAMPLE = REPO / "tests" / "daten" / "beispiel.de.txt"
|
||||||
|
GLOSSARY = REPO / "tests" / "daten" / "beispiel.glossar.txt"
|
||||||
SHARED_GLOSSARY = REPO / "krone-schmalz.glossar.txt"
|
SHARED_GLOSSARY = REPO / "krone-schmalz.glossar.txt"
|
||||||
|
SPEECHES = REPO / "testdaten"
|
||||||
# The autouse fixture below replaces it; tests of the real function use this
|
# The autouse fixture below replaces it; tests of the real function use this
|
||||||
REAL_FIND_MERGE_SIDE = ak.find_merge_side
|
REAL_FIND_MERGE_SIDE = ak.find_merge_side
|
||||||
|
|
||||||
|
|
@ -130,19 +132,34 @@ SAMPLE_GLOSSARIES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# The real speeches are not in the repository (copyright); without them these skip
|
||||||
|
needs_speeches = pytest.mark.skipif(
|
||||||
|
not all((SPEECHES / sample).is_file() for _, sample in SAMPLE_GLOSSARIES),
|
||||||
|
reason="echte Reden nur lokal in testdaten/",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_own_sample_glossary_replacements_all_match(capsys):
|
||||||
|
text = flat(SAMPLE.read_text(encoding="utf-8"))
|
||||||
|
ak.apply_replacements(text, ak.read_glossary(GLOSSARY)[1])
|
||||||
|
assert "ohne Treffer" not in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
@needs_speeches
|
||||||
@pytest.mark.parametrize("glossary, sample", SAMPLE_GLOSSARIES)
|
@pytest.mark.parametrize("glossary, sample", SAMPLE_GLOSSARIES)
|
||||||
def test_sample_glossary_replacements_all_match(capsys, glossary, sample):
|
def test_sample_glossary_replacements_all_match(capsys, glossary, sample):
|
||||||
"""Every rule in a speech glossary must hit its speech, after the shared one."""
|
"""Every rule in a speech glossary must hit its speech, after the shared one."""
|
||||||
text = flat((REPO / "testdaten" / sample).read_text(encoding="utf-8"))
|
text = flat((SPEECHES / sample).read_text(encoding="utf-8"))
|
||||||
text = ak.apply_replacements(text, ak.read_glossary(SHARED_GLOSSARY)[1])
|
text = ak.apply_replacements(text, ak.read_glossary(SHARED_GLOSSARY)[1])
|
||||||
capsys.readouterr()
|
capsys.readouterr()
|
||||||
ak.apply_replacements(text, ak.read_glossary(REPO / glossary)[1])
|
ak.apply_replacements(text, ak.read_glossary(REPO / glossary)[1])
|
||||||
assert "ohne Treffer" not in capsys.readouterr().out
|
assert "ohne Treffer" not in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
@needs_speeches
|
||||||
def test_shared_glossary_rules_match_some_speech():
|
def test_shared_glossary_rules_match_some_speech():
|
||||||
texts = [
|
texts = [
|
||||||
flat((REPO / "testdaten" / sample).read_text(encoding="utf-8"))
|
flat((SPEECHES / sample).read_text(encoding="utf-8"))
|
||||||
for _, sample in SAMPLE_GLOSSARIES
|
for _, sample in SAMPLE_GLOSSARIES
|
||||||
]
|
]
|
||||||
for wrong, right in ak.read_glossary(SHARED_GLOSSARY)[1]:
|
for wrong, right in ak.read_glossary(SHARED_GLOSSARY)[1]:
|
||||||
|
|
@ -392,7 +409,7 @@ def test_build_paragraphs_asks_where_short_paragraphs_belong(tmp_path, monkeypat
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def sample_copy(tmp_path):
|
def sample_copy(tmp_path):
|
||||||
path = tmp_path / "ramstein.de.txt"
|
path = tmp_path / "beispiel.de.txt"
|
||||||
shutil.copy(SAMPLE, path)
|
shutil.copy(SAMPLE, path)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
@ -400,19 +417,19 @@ def sample_copy(tmp_path):
|
||||||
def test_main_default_output_resume_and_glossary(sample_copy, monkeypatch, capsys):
|
def test_main_default_output_resume_and_glossary(sample_copy, monkeypatch, capsys):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-g", SHARED_GLOSSARY, "-g", GLOSSARY)
|
run_main(monkeypatch, "-i", sample_copy, "-g", GLOSSARY)
|
||||||
|
|
||||||
target = sample_copy.with_name("ramstein.de.korrigiert.txt")
|
target = sample_copy.with_name("beispiel.de.korrigiert.txt")
|
||||||
result = target.read_text(encoding="utf-8")
|
result = target.read_text(encoding="utf-8")
|
||||||
assert "Ramstein" in result and "Rammstein" not in result
|
assert "Auental" in result and "Auen Tal" not in result
|
||||||
assert "Kreml" in result and "1983" in result
|
assert "Haberkamp" in result and "1274" in result
|
||||||
assert (sample_copy.parent / "ramstein.de.korrigiert.parts").is_dir()
|
assert (sample_copy.parent / "beispiel.de.korrigiert.parts").is_dir()
|
||||||
assert "WARNUNG" not in capsys.readouterr().out
|
assert "WARNUNG" not in capsys.readouterr().out
|
||||||
|
|
||||||
# Second run: everything cached, no model calls
|
# Second run: everything cached, no model calls
|
||||||
monkeypatch.setattr(ak, "correct_chunk", no_model_calls)
|
monkeypatch.setattr(ak, "correct_chunk", no_model_calls)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", no_model_calls)
|
monkeypatch.setattr(ak, "find_paragraph_starts", no_model_calls)
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-g", SHARED_GLOSSARY, "-g", GLOSSARY)
|
run_main(monkeypatch, "-i", sample_copy, "-g", GLOSSARY)
|
||||||
assert target.read_text(encoding="utf-8") == result
|
assert target.read_text(encoding="utf-8") == result
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -425,7 +442,7 @@ def test_main_overwrites_own_output(sample_copy, monkeypatch, capsys):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
target = sample_copy.with_name("ramstein.de.korrigiert.txt")
|
target = sample_copy.with_name("beispiel.de.korrigiert.txt")
|
||||||
|
|
||||||
# Unchanged output of the last run is replaced by a different result
|
# Unchanged output of the last run is replaced by a different result
|
||||||
monkeypatch.setattr(ak, "correct_chunk", shouting)
|
monkeypatch.setattr(ak, "correct_chunk", shouting)
|
||||||
|
|
@ -439,7 +456,7 @@ def test_main_keeps_hand_edited_output(sample_copy, monkeypatch, capsys):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
target = sample_copy.with_name("ramstein.de.korrigiert.txt")
|
target = sample_copy.with_name("beispiel.de.korrigiert.txt")
|
||||||
edited = target.read_text(encoding="utf-8") + "Von Hand ergänzt.\n"
|
edited = target.read_text(encoding="utf-8") + "Von Hand ergänzt.\n"
|
||||||
target.write_text(edited, encoding="utf-8")
|
target.write_text(edited, encoding="utf-8")
|
||||||
capsys.readouterr()
|
capsys.readouterr()
|
||||||
|
|
@ -447,10 +464,10 @@ def test_main_keeps_hand_edited_output(sample_copy, monkeypatch, capsys):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", shouting)
|
monkeypatch.setattr(ak, "correct_chunk", shouting)
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-m", "anderes:modell")
|
run_main(monkeypatch, "-i", sample_copy, "-m", "anderes:modell")
|
||||||
|
|
||||||
new = sample_copy.with_name("ramstein.de.neu.korrigiert.txt")
|
new = sample_copy.with_name("beispiel.de.neu.korrigiert.txt")
|
||||||
assert target.read_text(encoding="utf-8") == edited
|
assert target.read_text(encoding="utf-8") == edited
|
||||||
assert "VIELEN DANK" in new.read_text(encoding="utf-8")
|
assert "VIELEN DANK" in new.read_text(encoding="utf-8")
|
||||||
assert sample_copy.with_name("ramstein.de.neu.aenderungen.html").is_file()
|
assert sample_copy.with_name("beispiel.de.neu.aenderungen.html").is_file()
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert f"WARNUNG: {target} wurde seit dem letzten Lauf geändert" in out
|
assert f"WARNUNG: {target} wurde seit dem letzten Lauf geändert" in out
|
||||||
assert f"Fertig: {new}" in out
|
assert f"Fertig: {new}" in out
|
||||||
|
|
@ -461,14 +478,14 @@ def test_main_keeps_hand_edited_output(sample_copy, monkeypatch, capsys):
|
||||||
|
|
||||||
|
|
||||||
def test_main_keeps_differing_output_without_checksum(sample_copy, monkeypatch, capsys):
|
def test_main_keeps_differing_output_without_checksum(sample_copy, monkeypatch, capsys):
|
||||||
target = sample_copy.with_name("ramstein.de.korrigiert.txt")
|
target = sample_copy.with_name("beispiel.de.korrigiert.txt")
|
||||||
target.write_text("Älteres Ergebnis, Herkunft unbekannt.\n", encoding="utf-8")
|
target.write_text("Älteres Ergebnis, Herkunft unbekannt.\n", encoding="utf-8")
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
|
|
||||||
assert target.read_text(encoding="utf-8") == "Älteres Ergebnis, Herkunft unbekannt.\n"
|
assert target.read_text(encoding="utf-8") == "Älteres Ergebnis, Herkunft unbekannt.\n"
|
||||||
assert sample_copy.with_name("ramstein.de.neu.korrigiert.txt").is_file()
|
assert sample_copy.with_name("beispiel.de.neu.korrigiert.txt").is_file()
|
||||||
assert "WARNUNG" in capsys.readouterr().out
|
assert "WARNUNG" in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -498,36 +515,36 @@ def test_main_output_option_creates_directories(sample_copy, monkeypatch):
|
||||||
def test_main_vtt_input_matches_txt_input(sample_copy, monkeypatch):
|
def test_main_vtt_input_matches_txt_input(sample_copy, monkeypatch):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
vtt = sample_copy.parent / "vtt" / "ramstein.de.vtt"
|
vtt = sample_copy.parent / "vtt" / "beispiel.de.vtt"
|
||||||
vtt.parent.mkdir()
|
vtt.parent.mkdir()
|
||||||
shutil.copy(SAMPLE.with_suffix(".vtt"), vtt)
|
shutil.copy(SAMPLE.with_suffix(".vtt"), vtt)
|
||||||
|
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
run_main(monkeypatch, "-i", vtt)
|
run_main(monkeypatch, "-i", vtt)
|
||||||
expected = sample_copy.with_name("ramstein.de.korrigiert.txt")
|
expected = sample_copy.with_name("beispiel.de.korrigiert.txt")
|
||||||
assert vtt.with_name("ramstein.de.korrigiert.txt").read_text(
|
assert vtt.with_name("beispiel.de.korrigiert.txt").read_text(
|
||||||
encoding="utf-8"
|
encoding="utf-8"
|
||||||
) == expected.read_text(encoding="utf-8")
|
) == expected.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
def test_main_writes_change_report(sample_copy, monkeypatch, capsys):
|
def test_main_writes_change_report(sample_copy, monkeypatch, capsys):
|
||||||
def correct(chunk, index, system):
|
def correct(chunk, index, system):
|
||||||
return chunk.strip().replace("Rammstein", "Ramstein")
|
return chunk.strip().replace("Linden Brunn", "Lindenbrunn")
|
||||||
|
|
||||||
monkeypatch.setattr(ak, "correct_chunk", correct)
|
monkeypatch.setattr(ak, "correct_chunk", correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
|
|
||||||
report = sample_copy.with_name("ramstein.de.aenderungen.html")
|
report = sample_copy.with_name("beispiel.de.aenderungen.html")
|
||||||
assert "title='Original: Rammstein" in report.read_text(encoding="utf-8")
|
assert "title='Original: Linden Brunn" in report.read_text(encoding="utf-8")
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert "„Rammstein“ → „Ramstein“" in out
|
assert "„Linden Brunn“ → „Lindenbrunn“" in out
|
||||||
assert f"Bericht: {report}" in out
|
assert f"Bericht: {report}" in out
|
||||||
|
|
||||||
|
|
||||||
def test_main_report_suspects_only_model_changes(sample_copy, monkeypatch, capsys):
|
def test_main_report_suspects_only_model_changes(sample_copy, monkeypatch, capsys):
|
||||||
glossary = sample_copy.with_name("g.txt")
|
glossary = sample_copy.with_name("g.txt")
|
||||||
glossary.write_text("Rammstein => Ramstein\n", encoding="utf-8")
|
glossary.write_text("Linden Brunn => Lindenbrunn\n", encoding="utf-8")
|
||||||
|
|
||||||
def correct(chunk, index, system):
|
def correct(chunk, index, system):
|
||||||
return chunk.strip().replace(" das ", " dies ", 1)
|
return chunk.strip().replace(" das ", " dies ", 1)
|
||||||
|
|
@ -536,9 +553,9 @@ def test_main_report_suspects_only_model_changes(sample_copy, monkeypatch, capsy
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-g", glossary)
|
run_main(monkeypatch, "-i", sample_copy, "-g", glossary)
|
||||||
|
|
||||||
page = sample_copy.with_name("ramstein.de.aenderungen.html").read_text(encoding="utf-8")
|
page = sample_copy.with_name("beispiel.de.aenderungen.html").read_text(encoding="utf-8")
|
||||||
section = page.split("<h2>Zu prüfen")[1].split("<h2>Alle Änderungen")[0]
|
section = page.split("<h2>Zu prüfen")[1].split("<h2>Alle Änderungen")[0]
|
||||||
assert "Rammstein" in page and "Rammstein" not in section
|
assert "Linden Brunn" in page and "Linden Brunn" not in section
|
||||||
assert "dies" in section
|
assert "dies" in section
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert "gültiges Wort ersetzt: „das“ → „dies“" in out
|
assert "gültiges Wort ersetzt: „das“ → „dies“" in out
|
||||||
|
|
@ -549,7 +566,7 @@ def test_main_without_change_report(sample_copy, monkeypatch):
|
||||||
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
monkeypatch.setattr(ak, "correct_chunk", identity_correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
run_main(monkeypatch, "-i", sample_copy, "--kein-bericht")
|
run_main(monkeypatch, "-i", sample_copy, "--kein-bericht")
|
||||||
assert not sample_copy.with_name("ramstein.de.aenderungen.html").exists()
|
assert not sample_copy.with_name("beispiel.de.aenderungen.html").exists()
|
||||||
|
|
||||||
|
|
||||||
def test_main_model_option(sample_copy, monkeypatch):
|
def test_main_model_option(sample_copy, monkeypatch):
|
||||||
|
|
@ -562,7 +579,7 @@ def test_main_model_option(sample_copy, monkeypatch):
|
||||||
|
|
||||||
monkeypatch.setattr(ak, "correct_chunk", correct)
|
monkeypatch.setattr(ak, "correct_chunk", correct)
|
||||||
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5))
|
||||||
parts = sample_copy.parent / "ramstein.de.korrigiert.parts"
|
parts = sample_copy.parent / "beispiel.de.korrigiert.parts"
|
||||||
|
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
default_parts = {p.name for p in parts.glob("part*")}
|
default_parts = {p.name for p in parts.glob("part*")}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,10 @@ import pytest
|
||||||
import vtt2txt
|
import vtt2txt
|
||||||
|
|
||||||
REPO = Path(__file__).resolve().parent.parent
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
SAMPLE_VTT = REPO / "testdaten" / "ramstein.de.vtt"
|
# Own, made-up sample speech; real speeches are only kept locally in testdaten/
|
||||||
SAMPLE_TXT = REPO / "testdaten" / "ramstein.de.txt"
|
SAMPLE_VTT = REPO / "tests" / "daten" / "beispiel.de.vtt"
|
||||||
|
SAMPLE_TXT = REPO / "tests" / "daten" / "beispiel.de.txt"
|
||||||
|
SPEECHES = REPO / "testdaten"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
@ -107,15 +109,27 @@ def test_is_rolling(cues, expected):
|
||||||
|
|
||||||
def test_main_default_output_matches_sample(sample_copy, monkeypatch, capsys):
|
def test_main_default_output_matches_sample(sample_copy, monkeypatch, capsys):
|
||||||
run_main(monkeypatch, "-i", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy)
|
||||||
target = sample_copy.with_name("ramstein.de.txt")
|
target = sample_copy.with_name("beispiel.de.txt")
|
||||||
assert target.read_text(encoding="utf-8") == SAMPLE_TXT.read_text(encoding="utf-8")
|
assert target.read_text(encoding="utf-8") == SAMPLE_TXT.read_text(encoding="utf-8")
|
||||||
assert f"Erstellt: {target}" in capsys.readouterr().out
|
assert f"Erstellt: {target}" in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("name", ["ramstein.de", "magdeburg.de-orig", "Lahnstein.de-orig"])
|
def speech(name):
|
||||||
def test_sample_vtt_gives_sample_txt(name):
|
"""A real speech, only kept locally (copyright): skipped without it."""
|
||||||
vtt = (REPO / "testdaten" / f"{name}.vtt").read_text(encoding="utf-8-sig")
|
path = SPEECHES / name
|
||||||
txt = (REPO / "testdaten" / f"{name}.txt").read_text(encoding="utf-8")
|
return pytest.param(path, marks=pytest.mark.skipif(
|
||||||
|
not path.is_file(), reason="echte Reden nur lokal in testdaten/"
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("vtt_path", [
|
||||||
|
SAMPLE_VTT,
|
||||||
|
speech("ramstein.de.vtt"), speech("magdeburg.de-orig.vtt"),
|
||||||
|
speech("Lahnstein.de-orig.vtt"),
|
||||||
|
])
|
||||||
|
def test_sample_vtt_gives_sample_txt(vtt_path):
|
||||||
|
vtt = vtt_path.read_text(encoding="utf-8-sig")
|
||||||
|
txt = vtt_path.with_suffix(".txt").read_text(encoding="utf-8")
|
||||||
assert vtt2txt.vtt_to_lines(vtt) == txt.splitlines()
|
assert vtt2txt.vtt_to_lines(vtt) == txt.splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -128,9 +142,9 @@ def test_main_multiple_inputs(sample_copy, monkeypatch):
|
||||||
|
|
||||||
|
|
||||||
def test_main_expands_glob_without_duplicates(sample_copy, monkeypatch, capsys):
|
def test_main_expands_glob_without_duplicates(sample_copy, monkeypatch, capsys):
|
||||||
shutil.copy(sample_copy, sample_copy.with_name("ramstein.en.vtt"))
|
shutil.copy(sample_copy, sample_copy.with_name("beispiel.en.vtt"))
|
||||||
shutil.copy(sample_copy, sample_copy.with_name("anders.de.vtt"))
|
shutil.copy(sample_copy, sample_copy.with_name("anders.de.vtt"))
|
||||||
run_main(monkeypatch, "-i", sample_copy.parent / "ramstein.*.vtt", sample_copy)
|
run_main(monkeypatch, "-i", sample_copy.parent / "beispiel.*.vtt", sample_copy)
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert out.count("Erstellt:") == 2
|
assert out.count("Erstellt:") == 2
|
||||||
assert not sample_copy.with_name("anders.de.txt").exists()
|
assert not sample_copy.with_name("anders.de.txt").exists()
|
||||||
|
|
@ -144,7 +158,7 @@ def test_main_output_directory(sample_copy, monkeypatch, make_dir, suffix):
|
||||||
if make_dir:
|
if make_dir:
|
||||||
out_dir.mkdir()
|
out_dir.mkdir()
|
||||||
run_main(monkeypatch, "-i", sample_copy, second, "-o", f"{out_dir}{suffix}")
|
run_main(monkeypatch, "-i", sample_copy, second, "-o", f"{out_dir}{suffix}")
|
||||||
assert (out_dir / "ramstein.de.txt").is_file()
|
assert (out_dir / "beispiel.de.txt").is_file()
|
||||||
assert (out_dir / "rede.en.txt").is_file()
|
assert (out_dir / "rede.en.txt").is_file()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -176,7 +190,7 @@ def test_main_bad_file_continues_batch(sample_copy, monkeypatch, capsys, content
|
||||||
(["-i", "{txt}"], "Keine VTT-Datei"),
|
(["-i", "{txt}"], "Keine VTT-Datei"),
|
||||||
(["-i", "{vtt}", "{vtt2}", "-o", "{dir}/x.txt"], "muss -o/--output ein Verzeichnis sein"),
|
(["-i", "{vtt}", "{vtt2}", "-o", "{dir}/x.txt"], "muss -o/--output ein Verzeichnis sein"),
|
||||||
(["-i", "{dir}/*.gibtsnicht"], "Keine Datei passt zu"),
|
(["-i", "{dir}/*.gibtsnicht"], "Keine Datei passt zu"),
|
||||||
(["-i", "{vtt}", "{dir}/sub/ramstein.de.vtt", "-o", "{dir}/"], "dieselbe Ausgabedatei"),
|
(["-i", "{vtt}", "{dir}/sub/beispiel.de.vtt", "-o", "{dir}/"], "dieselbe Ausgabedatei"),
|
||||||
(["-i", "{vtt}", "-o", "{vtt}"], "nicht die Eingabedatei"),
|
(["-i", "{vtt}", "-o", "{vtt}"], "nicht die Eingabedatei"),
|
||||||
])
|
])
|
||||||
def test_cli_errors(sample_copy, monkeypatch, capsys, args, message):
|
def test_cli_errors(sample_copy, monkeypatch, capsys, args, message):
|
||||||
|
|
@ -417,7 +431,7 @@ def test_split_segments_inverts_join_segments():
|
||||||
|
|
||||||
def test_main_time_range_default_name(sample_copy, monkeypatch):
|
def test_main_time_range_default_name(sample_copy, monkeypatch):
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-z", "0:00:30-0:01")
|
run_main(monkeypatch, "-i", sample_copy, "-z", "0:00:30-0:01")
|
||||||
target = sample_copy.with_name("ramstein.de_00-00-30_bis_00-01-00.txt")
|
target = sample_copy.with_name("beispiel.de_00-00-30_bis_00-01-00.txt")
|
||||||
full = SAMPLE_TXT.read_text(encoding="utf-8").splitlines()
|
full = SAMPLE_TXT.read_text(encoding="utf-8").splitlines()
|
||||||
part = target.read_text(encoding="utf-8").splitlines()
|
part = target.read_text(encoding="utf-8").splitlines()
|
||||||
assert vtt2txt.HEADER.fullmatch(part[0])
|
assert vtt2txt.HEADER.fullmatch(part[0])
|
||||||
|
|
@ -426,17 +440,17 @@ def test_main_time_range_default_name(sample_copy, monkeypatch):
|
||||||
|
|
||||||
def test_main_several_ranges(sample_copy, monkeypatch):
|
def test_main_several_ranges(sample_copy, monkeypatch):
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-z", "0:01-0:02 0:05")
|
run_main(monkeypatch, "-i", sample_copy, "-z", "0:01-0:02 0:05")
|
||||||
target = sample_copy.with_name("ramstein.de_00-01-00_bis_00-02-00+ab_00-05-00.txt")
|
target = sample_copy.with_name("beispiel.de_00-01-00_bis_00-02-00+ab_00-05-00.txt")
|
||||||
segments = vtt2txt.split_segments(target.read_text(encoding="utf-8"))
|
segments = vtt2txt.split_segments(target.read_text(encoding="utf-8"))
|
||||||
assert [header for header, _ in segments] == [
|
assert [header for header, _ in segments] == [
|
||||||
"[00:00:56 - 00:02:09]", "[00:04:57 - 00:48:07]",
|
"[00:00:59 - 00:02:03]", "[00:04:58 - 00:13:10]",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("ranges", [["0:01-0:02 0:05"], ["0:01-0:02", "0:05"]])
|
@pytest.mark.parametrize("ranges", [["0:01-0:02 0:05"], ["0:01-0:02", "0:05"]])
|
||||||
def test_main_ranges_with_or_without_quotes(sample_copy, monkeypatch, ranges):
|
def test_main_ranges_with_or_without_quotes(sample_copy, monkeypatch, ranges):
|
||||||
run_main(monkeypatch, "-i", sample_copy, "-z", *ranges)
|
run_main(monkeypatch, "-i", sample_copy, "-z", *ranges)
|
||||||
target = sample_copy.with_name("ramstein.de_00-01-00_bis_00-02-00+ab_00-05-00.txt")
|
target = sample_copy.with_name("beispiel.de_00-01-00_bis_00-02-00+ab_00-05-00.txt")
|
||||||
assert target.is_file()
|
assert target.is_file()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -456,8 +470,8 @@ def test_range_argv(argv, expected):
|
||||||
def test_main_range_from_beginning(sample_copy, monkeypatch, ranges):
|
def test_main_range_from_beginning(sample_copy, monkeypatch, ranges):
|
||||||
args = ranges if ranges[0].startswith("-z") else ["-z", *ranges]
|
args = ranges if ranges[0].startswith("-z") else ["-z", *ranges]
|
||||||
run_main(monkeypatch, "-i", sample_copy, *args)
|
run_main(monkeypatch, "-i", sample_copy, *args)
|
||||||
target = sample_copy.with_name("ramstein.de_bis_00-01-00.txt")
|
target = sample_copy.with_name("beispiel.de_bis_00-01-00.txt")
|
||||||
assert target.read_text(encoding="utf-8").startswith("[00:00:09 - ")
|
assert target.read_text(encoding="utf-8").startswith("[00:00:00 - ")
|
||||||
|
|
||||||
|
|
||||||
def test_main_time_range_without_captions(sample_copy, monkeypatch, capsys):
|
def test_main_time_range_without_captions(sample_copy, monkeypatch, capsys):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue