diff --git a/.gitignore b/.gitignore index 0e9e459..88d671a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,11 @@ __pycache__/ # Eigene Ergebnisse und Testläufe output/ + +# Echte Reden (Urheberrecht): nur lokal; die Tests nutzen tests/daten/ +testdaten/ + +# Glossare echter Beiträge (Namen, Hörfehler): nur lokal; ins Repository gehört +# nur das Glossar der erfundenen Beispielrede +*.glossar.txt +!tests/daten/beispiel.glossar.txt diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index bf1b34f..283c5a4 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -149,6 +149,16 @@ Mit eigenem Dateinamen: # → lahnstein.korrigiert.txt, lahnstein.txt (Rohtext), lahnstein.aenderungen.html ``` +**Ausprobieren ohne YouTube:** Im Ordner `tests/daten/` liegt eine frei erfundene +Beispielrede (Festrede zum Jubiläum der Gemeinde „Auental“) mit typischen Hörfehlern +und einem passenden Glossar. Ein Lauf dauert etwa zwei bis drei Minuten und zeigt alle +Ergebnisse, auch den Änderungsbericht: + +```bash +./abschrift_korrigieren.py -i tests/daten/beispiel.de.txt -g tests/daten/beispiel.glossar.txt -o beispiel.korrigiert.txt +# → beispiel.korrigiert.txt, beispiel.aenderungen.html +``` + --- ## 4. Der Arbeitsablauf im Überblick @@ -213,10 +223,10 @@ versteht `abschrift_korrigieren.py`. Soll die Original-Untertiteldatei (`.vtt`, mit Zeitstempeln) erhalten bleiben: ```bash -./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d testdaten -# → testdaten/Lahnstein.de-orig.vtt -./vtt2txt.py -i testdaten/Lahnstein.de-orig.vtt -# → testdaten/Lahnstein.de-orig.txt +./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d untertitel +# → untertitel/Lahnstein.de-orig.vtt +./vtt2txt.py -i untertitel/Lahnstein.de-orig.vtt +# → untertitel/Lahnstein.de-orig.txt ``` Achtung: `yt_untertitel.py` nimmt ohne `-l` Deutsch (`de`), nicht die @@ -293,9 +303,13 @@ Namen und Hörfehler) plus eines **je Beitrag**: ``` Das gemeinsame Glossar zuerst angeben, damit seine Ersetzungen zuerst greifen. -Im Programmordner liegen Beispiele: `krone-schmalz.glossar.txt` (gemeinsam), -`ramstein.glossar.txt`, `magdeburg.glossar.txt`, `lahnstein.glossar.txt` -(je eine Rede) und `iamfabian.glossar.txt` (Kanal über KI-Coding-Tools). + +Glossare enthalten Namen realer Personen und Hörfehler realer Beiträge. Sie werden +deshalb nicht ins Git-Repository übernommen: Jede Datei `*.glossar.txt` ist über +`.gitignore` ausgeschlossen und bleibt nur auf dem eigenen Rechner. Das ist +gewollt; Glossare lieber gesondert sichern. Einzige Ausnahme ist das kleine, +leicht nachvollziehbare Glossar zur erfundenen Beispielrede in +`tests/daten/beispiel.glossar.txt`, das sich gut als Vorlage eignet. ### 6.3 Entwurf vom Modell: `glossar_vorschlag.py` @@ -365,7 +379,9 @@ Statt `-i rede.txt` geht auch `-i rede.de.vtt` (Untertiteldatei) oder 4. **Korrektur:** Der Text wird in Abschnitte von etwa 1200 Wörtern geteilt, immer am Satzende, und Abschnitt für Abschnitt korrigiert. Abkürzungen wie „z. B.“, „Dr.“, „bzw.“ und Ordnungszahlen wie „2. Weltkrieg“ gelten dabei nicht als - Satzende. + Satzende. Das Modell ist angewiesen, nichts zu ergänzen, auch keine Vornamen oder + Titel aus dem Glossar: Steht dort „Alexander Dobrindt“, bleibt ein gesagtes + „Dobrindt“ trotzdem „Dobrindt“. 5. **Wortzahl-Prüfung:** Weicht die Wortzahl eines Abschnitts um mehr als 5 % ab, warnt das Programm (das Modell könnte etwas ausgelassen oder ergänzt haben). 6. **Absätze:** Das Modell nennt die Sätze, mit denen ein neuer Absatz beginnt; der @@ -399,10 +415,11 @@ Fertig: rede.korrigiert.txt Änderungen gegenüber dem Rohtext: 82 5× „Rammstein“ → „Ramstein“ … -Zu prüfen: 19 Stellen ← diese Stellen ansehen! +Zu prüfen: 20 Stellen (davon 2 Wortformen) ← diese Stellen ansehen! gültiges Wort ersetzt: „in“ → „dass“ stark verändert: „OSola“ → „Ursula“ … + Wortform geändert: „sehe“ → „sähe“ ← Wortformen am Ende Bericht: rede.aenderungen.html 19 Stelle(n) zu prüfen, siehe rede.aenderungen.html @@ -444,7 +461,8 @@ xdg-open rede.aenderungen.html 1. **Kopfzeile:** Wortzahlen, Anzahl der Ersetzungen, Einfügungen, Streichungen, Prüfmarken und Stellen „zu prüfen“. 2. **Zu prüfen:** Tabelle der verdächtigen Änderungen mit Grund, Text vorher, - korrigiertem Text und Zusammenhang. **Hier beginnen.** + korrigiertem Text und Zusammenhang. **Hier beginnen.** Darunter in einer eigenen + Tabelle die bloßen Wortformen („Wortform geändert“). 3. **Alle Änderungen nach Häufigkeit:** jede Wortänderung mit Anzahl, z. B. `5 Rammstein → Ramstein`. Gut, um wiederkehrende Hörfehler fürs Glossar zu finden. @@ -457,6 +475,7 @@ xdg-open rede.aenderungen.html | rot durchgestrichen | gestrichenes Wort | | orange `[prüfen: …]` | Prüfmarke des Modells | | rot umrahmt | Stelle „zu prüfen“; beim Darüberfahren erscheint der Grund | +| rot gestrichelt umrahmt | geänderte Wortform (meist Grammatik) | | rot umrahmtes ⚠ | hier hat das Modell eigenmächtig etwas gestrichen | Groß-/Kleinschreibung, Satzzeichen und Schreibweisen wie „z.B.“ → „z. B.“ werden @@ -470,19 +489,23 @@ Sinn verändern können. Was die Glossare ersetzt haben, erscheint hier nie. | Grund | Bedeutung | Beispiel | |---|---|---| | gültiges Wort ersetzt | Das alte Wort ist ein echtes Wort (steht in der Wortliste), also vermutlich kein Hörfehler. | „Professor“ → „Professorin“, „unterschreiben“ → „unterscheiden“ | +| Wortform geändert | Ein echtes Wort hat nur eine andere Endung oder einen Umlaut bekommen. Meist eine richtige Grammatik-Korrektur; steht in einer eigenen Gruppe am Ende. | „Punkten“ → „Punkte“, „das“ → „dass“, „sehe“ → „sähe“ | | stark verändert | Das neue Wort ähnelt dem alten kaum (unter 60 %). | „CT1“ → „ZDF“ | | eingefügt | Das Modell hat ein Wort ergänzt. | „∅“ → „ist“ | | gestrichen | Das Modell hat ein Wort weggelassen (Füllwörter wie „äh“ zählen nicht). | „Sicherungskonzepte geht“ → „∅“ | Nicht gemeldet werden ähnlich bleibende Hörfehler-Korrekturen („Gradwanderung“ → „Gratwanderung“), reine Zusammen-, Getrennt- und Bindestrich-Schreibung („Clan -Kriminalität“ → „Clankriminalität“) und Wörter, die im Glossar stehen. +Kriminalität“ → „Clankriminalität“) und Schreibweisen aus dem Glossar („Bar“ → +„Bahr“, wenn „Egon Bahr“ im Glossar steht). Ergänzt das Modell dagegen Wörter, etwa +einen Vornamen („Dobrind“ → „Alexander Dobrindt“), erscheint das auch dann, wenn der +volle Name im Glossar steht: Gesagt wurde er so nicht. **So arbeitet man die Liste ab:** 1. Für jede Zeile den Zusammenhang lesen. -2. Ist die Änderung richtig (oft bei Grammatik: „das“ → „dass“, „sehe“ → „sähe“), - nichts tun. +2. Ist die Änderung richtig, nichts tun. Bei den Wortformen am Ende ist das der + Normalfall; dort genügt ein kurzer Blick. 3. Ist sie falsch, im korrigierten Text zurückändern. Tritt der Fehler öfter auf oder geht es um einen Namen, besser das Glossar ergänzen (nächster Schritt). 4. Bei „gestrichen“ prüfen, ob wirklich etwas fehlt: Oft entfernt das Modell @@ -521,9 +544,22 @@ neu, was sich geändert hat: - Die Absatzgliederung wird für geänderte Textstellen ebenfalls neu bestimmt; das geht schnell. -Von Hand nachbearbeitete `*.korrigiert.txt` werden bei einem erneuten Lauf -**überschrieben**. Handarbeit deshalb erst ganz am Ende machen oder die Datei vorher -unter anderem Namen sichern. +**Handarbeit bleibt erhalten.** Wurde `rede.korrigiert.txt` seit dem letzten Lauf +von Hand geändert, überschreibt ein erneuter Lauf sie nicht. Das neue Ergebnis kommt +dann nach `rede.neu.korrigiert.txt` (Bericht: `rede.neu.aenderungen.html`), mit +einer Warnung: + +```text +WARNUNG: rede.korrigiert.txt wurde seit dem letzten Lauf geändert (von Hand?) und bleibt erhalten. Neues Ergebnis: rede.neu.korrigiert.txt (mit --ueberschreiben wird die Datei ersetzt) +``` + +Die eigenen Änderungen lassen sich dann mit einem Vergleichsprogramm übertragen, +z. B. `meld rede.korrigiert.txt rede.neu.korrigiert.txt`. Soll die Handarbeit +verworfen werden: `--ueberschreiben` angeben. + +Das Programm erkennt Handarbeit an einer Prüfsumme in `rede.korrigiert.parts/`. +Fehlt sie (erster Lauf mit dieser Version, Ordner gelöscht), gilt jede abweichende +vorhandene Datei als von Hand geändert. --- @@ -543,6 +579,8 @@ Option kennen `extract_text.py` und `vtt2txt.py`. > **Vorsicht:** `05:00` bedeutet 5 Stunden, nicht 5 Minuten. Für „5 Minuten“ > `00:05` oder `5` schreiben, für 5 Minuten 30 Sekunden `00:05:30`. +> Reicht ein Bereich über das Ende des Videos hinaus, weist das Programm darauf hin +> und nennt die Länge der Untertitel. ### 10.2 Bereiche @@ -615,7 +653,7 @@ Beispiel für `-i rede.txt` bzw. `-o rede.korrigiert.txt`: | Datei | Inhalt | Wird überschrieben? | |---|---|---| | `rede.txt` | Rohtext (bei `-u` automatisch gespeichert) | nie, wenn sie schon mit anderem Inhalt existiert (dann Warnung) | -| `rede.korrigiert.txt` | korrigierte Abschrift | ja, bei jedem Lauf | +| `rede.korrigiert.txt` | korrigierte Abschrift | ja, außer sie wurde von Hand geändert (dann `rede.neu.korrigiert.txt`, siehe [Abschnitt 9](#9-schritt-5-nachbessern-und-erneut-laufen-lassen)) | | `rede.aenderungen.html` | Änderungsbericht | ja, bei jedem Lauf | | `rede.korrigiert.parts/` | Zwischenstände | wird ergänzt; darf jederzeit gelöscht werden | | `rede.glossar.entwurf.txt` | Glossar-Entwurf von `glossar_vorschlag.py` | ja | @@ -690,12 +728,14 @@ Weitere Einstellungen (Abschnittsgröße, Absatzlängen, Schwellen) sind in der | `Die Eingabedatei ist leer.` | Datei prüfen. | | `Ausgabedatei darf nicht die Eingabedatei sein.` | Mit `-o` einen anderen Namen wählen. | | `Glossar nicht gefunden: …` | Pfad bei `-g` prüfen. | +| `WARNUNG: rede.korrigiert.txt wurde seit dem letzten Lauf geändert (von Hand?) …` | Die Datei wurde nachbearbeitet und bleibt erhalten; das neue Ergebnis steht in `rede.neu.korrigiert.txt`. Änderungen übertragen oder mit `--ueberschreiben` ersetzen, siehe [Abschnitt 9](#9-schritt-5-nachbessern-und-erneut-laufen-lassen). | | `WARNUNG: rede.txt existiert mit anderem Inhalt und bleibt unverändert.` | Bei `-u` wird ein vorhandener, z. B. von Hand bearbeiteter Rohtext nie überschrieben. Korrigiert wird trotzdem der frisch geladene Text. Wer den neuen Rohtext braucht, die alte Datei umbenennen. | | `WARNUNG: Abschnitt 3: 1180 → 1090 Wörter (8% Abweichung) …` | Das Modell hat möglicherweise etwas ausgelassen oder ergänzt. Abschnitt im Bericht prüfen. Bei Bedarf die genannte Datei in `.parts/` löschen und erneut laufen lassen. | | `Abschnitt 3 wurde abgeschnitten. CHUNK_SIZE verkleinern und erneut starten.` | Die Antwort des Modells war zu lang. `CHUNK_SIZE` oben in `abschrift_korrigieren.py` verkleinern (z. B. 900). | | `Absatzgliederung: unbrauchbare Antwort: …` / `Absätze verbinden: unbrauchbare Antwort: …` | Das Modell hat kein gültiges JSON geliefert; selten. Erneut starten, die Korrektur selbst ist zwischengespeichert. Tritt es wiederholt auf, ein anderes Modell versuchen. | | `Hinweis: keine Wortliste für „de“ (Paket wngerman); …` | `sudo apt install wngerman` (für Englisch `wamerican`). Ohne Wortliste fehlt im Bericht nur der Grund „gültiges Wort ersetzt“. | -| `Hinweis: keine Untertitel im Bereich …` | Einer von mehreren Bereichen ist leer und wird übersprungen. | +| `Hinweis: keine Untertitel im Bereich …` | Einer von mehreren Bereichen ist leer und wird übersprungen. In Klammern steht, wo die Untertitel enden. | +| `Hinweis: Bereich Anfang – 05:00:00 reicht über das Ende der Untertitel hinaus (…)` | Der Bereich endet nach dem Video. Meist war Minute statt Stunde gemeint: `05:00` ist Stunde 5, Minute 5 ist `00:05`. Bearbeitet wird trotzdem, bis zum Ende des Videos. | | `Keine Berechtigung` beim Start mit `./…` | `chmod +x *.py` oder `python3 programm.py …` aufrufen. | | Lauf ist extrem langsam | Das Modell passt nicht in den Grafikspeicher. `OLLAMA_NUM_PARALLEL=1` setzen (siehe [Abschnitt 2.2](#22-grafikkarte)), andere Programme mit Grafikspeicherbedarf schließen oder ein kleineres Modell wählen. Prüfen mit `ollama ps` (Spalte PROCESSOR sollte „100% GPU“ zeigen). | @@ -760,6 +800,7 @@ einfügen. | `-z BEREICH …` | nur diese Zeitbereiche (mit `.vtt` oder `-u`) | | `--exakt` | genau an den Zeiten schneiden | | `--kein-bericht` | keinen Änderungsbericht schreiben | +| `--ueberschreiben` | von Hand geänderte Ausgabedatei trotzdem ersetzen | ### `extract_text.py` diff --git a/README.md b/README.md index 7e7646e..d04fa9d 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,9 @@ Oder in zwei Schritten, um den Rohtext vorher anzusehen: Dasselbe in Einzelschritten, wenn die VTT-Datei erhalten bleiben soll: ```bash -./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d testdaten -./vtt2txt.py -i testdaten/Lahnstein.de-orig.vtt -./abschrift_korrigieren.py -i testdaten/Lahnstein.de-orig.txt +./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d untertitel +./vtt2txt.py -i untertitel/Lahnstein.de-orig.vtt +./abschrift_korrigieren.py -i untertitel/Lahnstein.de-orig.txt ``` Der Schritt über `vtt2txt.py` ist optional: `abschrift_korrigieren.py` nimmt auch die @@ -76,7 +76,7 @@ Zwischenschritt im temporären Verzeichnis. Die Spurwahl ist dieselbe wie bei ```bash ./extract_text.py -u 'https://www.youtube.com/watch?v=0LmCveTM788' # → 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 texte/rede.txt # Sprache und Ziel ./extract_text.py -u URL -f -o rede.txt # lesbarer Fließtext ./extract_text.py -u URL -z 0:03:17-0:05:25 # nur ein Ausschnitt ./extract_text.py -u URL -z 00:05-00:06 00:10-00:12 00:25 # mehrere Bereiche @@ -131,7 +131,7 @@ Region gefunden: `-l en` findet manuelle Untertitel `en-US`. ```bash ./yt_untertitel.py -u URL # → __.de-orig.vtt -./yt_untertitel.py -u URL -n Lahnstein -d testdaten # → testdaten/Lahnstein.de-orig.vtt +./yt_untertitel.py -u URL -n Lahnstein -d untertitel # → untertitel/Lahnstein.de-orig.vtt ``` | Option | Bedeutung | @@ -182,7 +182,9 @@ Gilt gleich für `vtt2txt.py`, `extract_text.py` und `abschrift_korrigieren.py`. | `25` | Minute 25 | Achtung: Zwei Zahlen sind Stunden:Minuten, `05:00` ist also Stunde 5, nicht -Minute 5 (dafür `00:05` oder `5`). +Minute 5 (dafür `00:05` oder `5`). Reicht ein Bereich über die letzte +Untertitelzeile hinaus, nennt ein Hinweis das Ende der Untertitel, bei Bereichen ab +einer Stunde mit diesem Tipp. | Aufruf | Text | |---|---| @@ -247,6 +249,12 @@ werden trotzdem umgewandelt; der Exit-Code ist dann 1. | `-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`) | | `--kein-bericht` | keinen Änderungsbericht schreiben | +| `--ueberschreiben` | Ausgabedatei auch ersetzen, wenn sie seit dem letzten Lauf von Hand geändert wurde | + +Eine von Hand nachbearbeitete Ausgabedatei überschreibt ein erneuter Lauf nicht: Das +Ergebnis kommt dann nach `.neu.korrigiert.txt`, mit Warnung. Erkannt wird das +an der Prüfsumme der zuletzt geschriebenen Ausgabe in `.parts/ausgabe.sha256`; +ohne Prüfsumme gilt jede abweichende vorhandene Datei als von Hand geändert. Mit Zeitauswahl wird jeder Bereich als eigener Block korrigiert und gegliedert; die Überschriften `[00:04:57 - 00:06:04]` bekommt das Modell nicht zu sehen, sie @@ -266,7 +274,9 @@ Blöcken korrigiert. 3. **Korrektur:** Der Text wird in Abschnitte von ca. 1200 Wörtern geteilt (immer am Satzende; Abkürzungen wie „z. B.“, „Dr.“, „bzw.“ und Ordnungszahlen wie „2. Weltkrieg“ zählen nicht als Satzende) und abschnittsweise vom Modell - korrigiert. Fortschritt wird live angezeigt. + korrigiert. Fortschritt wird live angezeigt. Der Prompt verbietet Ergänzungen, + ausdrücklich auch Vornamen, Titel oder Namensteile aus dem Glossar, die nicht + gesagt wurden (sonst wurde aus „Dobrindt“ gern „Alexander Dobrindt“). 4. **Wortzahl-Prüfung:** Weicht die Wortzahl eines Abschnitts um mehr als 5 % ab, gibt es eine Warnung (mögliche Auslassungen oder Ergänzungen). 5. **Absätze:** Das Modell nennt nur Satznummern, an denen ein Absatz beginnt; der @@ -311,15 +321,24 @@ Ersetzungen des Glossars), mit seinem Ergebnis. Gemeldet werden: | Grund | Beispiel | |---|---| | gültiges Wort ersetzt | „Professor“ → „Professorin“, „unterschreiben“ → „unterscheiden“ (das alte Wort steht in der Wortliste, war also kein Hörfehler) | +| Wortform geändert | „Punkten“ → „Punkte“, „das“ → „dass“, „sehe“ → „sähe“: ein gültiges Wort, nur Endung oder Umlaut anders (meist Grammatik); eigene Gruppe am Ende der Liste | | stark verändert | „CT1“ → „ZDF“ (Ähnlichkeit unter 60 %) | | eingefügt | „∅“ → „ist“ | | gestrichen | „Sicherungskonzepte geht“ → „∅“ (Füllwörter wie „äh“ nicht) | Nicht gemeldet werden Hörfehler-Korrekturen, die ähnlich bleiben („Gradwanderung“ → „Gratwanderung“), reine Zusammen-, Getrennt- und -Bindestrich-Schreibung („Clan Kriminalität“ → „Clankriminalität“) und neue Wörter, -die im Glossar stehen. Die Liste erscheint auch in der Konsole. Kleine -Grammatik-Korrekturen wie „das“ → „dass“ tauchen ebenfalls auf; ein Blick genügt. +Bindestrich-Schreibung („Clan Kriminalität“ → „Clankriminalität“) und Schreibweisen +aus dem Glossar („Bar“ → „Bahr“ bei „Egon Bahr“ im Glossar): Die neuen Wörter müssen +zusammenhängend in einem Glossareintrag stehen und dem alten Text ähneln. Einzelne +Allerweltswörter aus längeren Einträgen („Sie“ aus „finden Sie“) und eingefügte +Wörter (ein ergänzter Vorname „Alexander“) erklärt das Glossar nicht. Die Liste +erscheint auch in der Konsole, sinnverändernde Fälle zuerst, Wortformen danach. + +Als Wortform gilt ein einzelnes Wort, das bis auf die Endung gleich bleibt (Stamm +mindestens 3 Buchstaben, beide Endungen aus `INFLECTIONS`, z. B. -e, -n, -s, -en, +-er, -es, -st, -t) oder sich nur im Umlaut unterscheidet. „-in“ gehört bewusst nicht +dazu: „Professor“ → „Professorin“ bleibt in der Hauptliste. Für vorhandene Dateien gibt es das eigene Skript. Mit denselben Glossaren wie bei der Korrektur gelten deren Ersetzungen und Begriffe nicht als verdächtig: @@ -350,11 +369,14 @@ einzelnen Beitrag deutet das auf einen Tippfehler hin, bei einem gemeinsamen Glo es normal. Mehrere Glossare lassen sich kombinieren: ein gemeinsames für wiederkehrende Namen -und Hörfehler eines Redners oder Kanals und eines je Beitrag. Beispiel zu den Testdaten: -`krone-schmalz.glossar.txt` (gemeinsam) plus `ramstein.glossar.txt`, -`magdeburg.glossar.txt` bzw. `lahnstein.glossar.txt`. Das gemeinsame Glossar zuerst angeben, damit seine -Ersetzungen vor den speziellen greifen. Ein weiteres Kanal-Glossar: -`iamfabian.glossar.txt` für Videos über KI-Coding-Tools (Claude Code, Codex, OpenCode …). +und Hörfehler eines Redners oder Kanals und eines je Beitrag, z. B. +`krone-schmalz.glossar.txt` (gemeinsam) plus `ramstein.glossar.txt`. Das gemeinsame +Glossar zuerst angeben, damit seine Ersetzungen vor den speziellen greifen. + +Glossare gehören zu realen Beiträgen und Personen und werden deshalb nicht +versioniert: `*.glossar.txt` steht in `.gitignore`, eigene Glossare liegen nur lokal. +Im Repository ist als Beispiel nur `tests/daten/beispiel.glossar.txt` zur erfundenen +Beispielrede. ### Glossar-Entwurf: `glossar_vorschlag.py` @@ -379,9 +401,9 @@ erneut vorgeschlagen. Zeit-Überschriften von Ausschnitten Roh- und korrigiertem Text entfernt; das Modell bekommt sie nicht zu sehen. ```bash -./glossar_vorschlag.py -i testdaten/Lahnstein.de-orig.txt \ - -k testdaten/Lahnstein.de-orig.korrigiert.txt -g krone-schmalz.glossar.txt -# → testdaten/Lahnstein.de-orig.glossar.entwurf.txt +./glossar_vorschlag.py -i rede.txt -k rede.korrigiert.txt -g krone-schmalz.glossar.txt +# → rede.glossar.entwurf.txt +./glossar_vorschlag.py -i tests/daten/beispiel.de.txt # an der Beispielrede ausprobieren ``` | Option | Bedeutung | @@ -398,24 +420,31 @@ werden in `.parts/` zwischengespeichert. ## Testdaten -`testdaten/` enthält drei Reden, jeweils als automatische YouTube-Untertitel -(`.vtt`, Original) und daraus mit `vtt2txt.py` gewonnener Rohtext (`.txt`, Eingabe -für das Programm): +**Im Repository:** `tests/daten/` enthält eine frei erfundene Beispielrede +(Festrede zum Jubiläum der Gemeinde „Auental“; Ort und Personen gibt es nicht), als +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`, ebenso die Glossare (`*.glossar.txt`). +Liegen die drei Reden, mit denen das Programm entwickelt wurde, in `testdaten/` und +ihre Glossare im Programmordner, laufen zusätzlich die Tests, die diese Glossare +prüfen; sonst werden sie übersprungen: - `ramstein.de.*`: Rede über die US Air Base Ramstein (Glossar `ramstein.glossar.txt`) - `magdeburg.de-orig.*`: Rede in Magdeburg (Glossar `magdeburg.glossar.txt`) - `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. - -```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. +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. ## Tests @@ -423,27 +452,36 @@ Ein Lauf dauert mit `qwen3:32b` vollständig auf einer RTX 3090 etwa 6 Minuten. python3 -m pytest ``` -Die Tests (291) brauchen weder Ollama noch Netz: Modellaufrufe und `yt-dlp` werden -durch Fakes ersetzt. `tests/test_abschrift_korrigieren.py` prüft Abschnittsbildung, -Satzgrenzen (Abkürzungen und Ordnungszahlen sind kein Satzende), Glossar (inkl. -„jede Ersetzung im Glossar einer Rede trifft diese Rede, jede im gemeinsamen Glossar -trifft mindestens eine“), Streaming-Auswertung, Absatzgliederung (Text bleibt -unverändert, 3–10 Sätze), Verbinden kurzer Absätze (Modell wird nur gefragt, wenn -beide Nachbarn passen), Zwischenspeicher/Fortsetzen, Zeitauswahl, Sprachen und die +Die Tests brauchen weder Ollama noch Netz: Modellaufrufe und `yt-dlp` werden durch +Fakes ersetzt. Als Text dient die erfundene Beispielrede in `tests/daten/` (siehe +[Testdaten](#testdaten)). In einem frischen Klon laufen 318 Tests, 7 werden +übersprungen; sie prüfen die Glossare der echten Reden und laufen nur, wenn diese +lokal in `testdaten/` liegen (dann 325). + +`tests/test_abschrift_korrigieren.py` prüft Abschnittsbildung, Satzgrenzen +(Abkürzungen und Ordnungszahlen sind kein Satzende), Glossar (jede Ersetzung des +Beispielglossars trifft die Beispielrede; lokal zusätzlich: jede Ersetzung im +Glossar einer Rede trifft diese Rede, jede im gemeinsamen Glossar mindestens eine), +Prompts (keine Namensteile ergänzen), Streaming-Auswertung, Absatzgliederung (Text +bleibt unverändert, 3–10 Sätze), Verbinden kurzer Absätze (Modell wird nur gefragt, +wenn beide Nachbarn passen), Zwischenspeicher/Fortsetzen, Schutz von Handarbeit +(`.neu.korrigiert.txt`, `--ueberschreiben`), Zeitauswahl, Sprachen und die Kommandozeile. `tests/test_glossar_vorschlag.py` prüft Filter (nur Funde im Text, keine bekannten), Ausgabeformat (gültiges Glossar, Unsicheres auskommentiert) und Zwischenspeicher. `tests/test_aenderungen.py` prüft den Wortvergleich (Satzzeichen, Groß-/Kleinschreibung -und „z. B.“ zählen nicht), die Liste „Zu prüfen“ (Gründe, Ausnahmen, Glossar, -fehlende Wortliste) und den HTML-Bericht (vollständiger Text, Absätze, Escaping). +und „z. B.“ zählen nicht), die Liste „Zu prüfen“ (Gründe, Wortformen, Füllwörter je +Sprache, Glossar-Schreibweisen, fehlende Wortliste) und den HTML-Bericht +(vollständiger Text, Absätze, Escaping, Reihenfolge). Die Tests nutzen eine kleine eigene Wortliste statt der des Systems. `tests/test_extract_text.py` prüft den Gesamtablauf URL → Text, Sprachwahl (Original-Audio, manuell vor automatisch) und Fehlerfälle. `tests/test_yt_untertitel.py` prüft Spurauswahl, Aufruf von `yt-dlp` und Fehlerfälle (ohne Netz, `yt-dlp` wird durch Fakes ersetzt). -`tests/test_vtt2txt.py` prüft die VTT-Umwandlung: jede `.vtt` in `testdaten/` -ergibt genau die zugehörige `.txt`, echte Wiederholungen bleiben erhalten, auch bei -Untertiteln ohne rollendes Fenster, dazu Zeitauswahl, Muster, Ausgabeverzeichnis und +`tests/test_vtt2txt.py` prüft die VTT-Umwandlung: die Beispiel-`.vtt` (und lokal +jede Rede in `testdaten/`) ergibt genau die zugehörige `.txt`, echte Wiederholungen +bleiben erhalten, auch bei Untertiteln ohne rollendes Fenster, dazu Zeitauswahl +(mit Hinweis bei Bereichen über das Ende hinaus), Muster, Ausgabeverzeichnis und Fehlerfälle. ## Zwischenstände @@ -478,7 +516,9 @@ In `aenderungen.py`: |---|---|---| | `WORDLISTS` | `/usr/share/dict/ngerman`, `…/american-english` | Wortlisten je Sprache | | `MIN_SIMILARITY` | 0.6 | darunter gilt eine Ersetzung als „stark verändert“ | -| `FILLERS` | äh, ähm, … | Füllwörter, deren Streichung nicht gemeldet wird | +| `FILLERS` | je Sprache: äh, ähm, …; uh, um, er, … | Füllwörter, deren Streichung nicht gemeldet wird | +| `INFLECTIONS` | je Sprache: -e, -n, -s, -en, …; -s, -ed, -ing, … | Endungen, die nur die Wortform ändern | +| `MIN_STEM` | 3 | kürzester gemeinsamer Wortstamm einer Wortform-Änderung | In `vtt2txt.py`: diff --git a/abschrift_korrigieren.py b/abschrift_korrigieren.py index 02bc4b9..f8c3f69 100755 --- a/abschrift_korrigieren.py +++ b/abschrift_korrigieren.py @@ -14,7 +14,7 @@ import urllib.error import urllib.request from aenderungen import ( - REVIEW_MARK, glossary_words, print_summary, report_path, write_report, + REVIEW_MARK, glossary_entries, print_summary, report_path, write_report, ) from extract_text import fetch_text from vtt2txt import ( @@ -33,6 +33,7 @@ MAX_WORD_DEVIATION = 0.05 # ab dieser Abweichung der Wortzahl wird gewarnt PARAGRAPH_WINDOW = 150 # Sätze pro Anfrage bei der Absatzgliederung MAX_PARAGRAPH_SENTENCES = 10 # längere Absätze werden nachträglich geteilt MIN_PARAGRAPH_SENTENCES = 3 # kürzere Absätze werden mit dem Nachbarn verbunden +OUTPUT_RECORD = "ausgabe.sha256" # in .parts/: Prüfsumme der zuletzt geschriebenen Ausgabe SENTENCE_END = re.compile(r"[.!?…][\"'»«“”)\]]*$") SENTENCE_SPLIT = re.compile(r"(?:(?<=[.!?…])|(?<=[.!?…][\"'»«“”)\]]))\s+") @@ -57,6 +58,9 @@ Keine Zusammenfassung und keine stilistische Neufassung. - Entferne nur eindeutig technisch verursachte Untertitel-Dopplungen. - Bewahre rhetorische Wiederholungen und Selbstkorrekturen. - Ergänze keine Informationen und keine fehlenden Sätze. +- Ergänze keine Vornamen, Titel oder andere Namensteile, die nicht gesagt + wurden, auch nicht aus dem Glossar: Steht in der Abschrift nur ein + Nachname, bleibt es beim Nachnamen. - Glätte keine Formulierungen allein aus stilistischen Gründen. - Ändere Zahlen, Daten und Zitate nur bei eindeutigen Fehlern. - Übernimm Geräuschhinweise in eckigen Klammern wie [applaus] unverändert. @@ -123,6 +127,9 @@ No summary and no stylistic rewrite. speaker-change marker ">>". - Keep rhetorical repetitions and self-corrections. - Do not add information or missing sentences. +- Do not add first names, titles or other parts of a name that were not + said, not even from the glossary: if the transcript has only a surname, + keep only the surname. - Do not smooth phrasing for stylistic reasons alone. - Change numbers, dates and quotations only if they are clearly wrong. - Keep sound tags in square brackets such as [music] unchanged. @@ -180,7 +187,10 @@ PROMPTS = { "merge": MERGE_SYSTEM, "glossary": "Glossar: korrekte Schreibweisen von Namen und Begriffen, die in " "diesem Beitrag vorkommen. Falsch erkannte Varianten davon in der Abschrift " - "stillschweigend korrigieren:", + "stillschweigend korrigieren. Korrigiere nur die Schreibweise dessen, was " + "gesagt wurde: Ergänze keine Vornamen, Titel oder Namensteile aus dem Glossar, " + "die in der Abschrift fehlen (aus „Dobrind“ wird „Dobrindt“, nicht " + "„Alexander Dobrindt“).", "excerpt": "Der Text ist ein Ausschnitt aus einem längeren Beitrag und kann mitten " "im Satz beginnen oder enden. Vervollständige angeschnittene Sätze nicht und " "ergänze kein Wort, auch nicht in einer Markierung; lass einen unvollständigen " @@ -193,7 +203,10 @@ PROMPTS = { "merge": MERGE_SYSTEM_EN, "glossary": "Glossary: correct spellings of names and terms that occur in " "this recording. Silently correct misrecognized variants of them in the " - "transcript:", + "transcript. Correct only the spelling of what was said: do not add first " + "names, titles or other parts of a name from the glossary that are missing " + "in the transcript (\"Mearshimer\" becomes \"Mearsheimer\", not " + "\"John Mearsheimer\").", "excerpt": "The text is an excerpt from a longer recording and may begin or end " "in the middle of a sentence. Do not complete cut-off sentences and do not " "add any word, not even in a mark; leave an incomplete beginning or ending " @@ -227,7 +240,7 @@ def build_system(glossary, lang=DEFAULT_LANGUAGE, excerpt=False): if not glossary: return system terms = "\n".join(f"- {term}" for term in glossary) - return f"{system}\n{prompts['glossary']}\n{terms}\n" + return f"{system}\n{prompts['glossary']}\n\n{terms}\n" def read_glossary(path): @@ -635,6 +648,11 @@ def parse_args(): "--kein-bericht", action="store_true", help="keinen Änderungsbericht .aenderungen.html schreiben", ) + parser.add_argument( + "--ueberschreiben", action="store_true", + help="die Ausgabedatei auch dann überschreiben, wenn sie seit dem letzten Lauf " + "von Hand geändert wurde (sonst entsteht .neu.korrigiert.txt)", + ) add_time_options(parser) args = parser.parse_args(range_argv(sys.argv[1:])) resolve_time_ranges(parser, args) @@ -702,6 +720,35 @@ def read_source(args): return raw, args.output, base_language(args.lang or DEFAULT_LANGUAGE) +def text_hash(text): + return hashlib.sha256(text.encode("utf-8")).hexdigest() + + +def new_output_path(target): + """rede.korrigiert.txt -> rede.neu.korrigiert.txt, out.txt -> out.neu.txt""" + if target.name.endswith(".korrigiert.txt"): + stem = target.name.removesuffix(".korrigiert.txt") + return target.with_name(f"{stem}.neu.korrigiert.txt") + return target.with_name(f"{target.stem}.neu{target.suffix}") + + +def choose_output(target, content, parts_dir, overwrite=False): + """Where to write `content`: the target, unless it was changed by hand. + + A target counts as changed by hand if it differs both from what the last + run wrote there (checksum in parts_dir) and from the new content. Without + a checksum (first run, .parts deleted) any differing target counts. + """ + if overwrite or not target.exists(): + return target + current = target.read_text(encoding="utf-8") + record = parts_dir / OUTPUT_RECORD + last = record.read_text(encoding="utf-8").strip() if record.exists() else None + if current == content or text_hash(current) == last: + return target + return new_output_path(target) + + def main(): global MODEL args = parse_args() @@ -794,14 +841,25 @@ def main(): corrected_blocks.append((header, paragraphs)) text = join_segments(corrected_blocks, header_gap="\n\n") - target.write_text(text + "\n", encoding="utf-8") + content = text + "\n" + output = choose_output(target, content, parts_dir, args.ueberschreiben) + output.write_text(content, encoding="utf-8") + if output == target: + (parts_dir / OUTPUT_RECORD).write_text(text_hash(content) + "\n", encoding="utf-8") + else: + print( + f"WARNUNG: {target} wurde seit dem letzten Lauf geändert (von Hand?) und " + f"bleibt erhalten. Neues Ergebnis: {output} " + "(mit --ueberschreiben wird die Datei ersetzt)" + ) + target = output print(f"Fertig: {target}") if not args.kein_bericht: report = report_path(target) comparison = write_report( raw_text, text, report, target.name, model_input=model_text, - known=glossary_words(terms, replacements), lang=lang, + glossary=glossary_entries(terms, replacements), lang=lang, ) print_summary(comparison) print(f"Bericht: {report}") diff --git a/aenderungen.py b/aenderungen.py index adb7fe6..f2eca03 100755 --- a/aenderungen.py +++ b/aenderungen.py @@ -10,7 +10,7 @@ import argparse import html import re -from vtt2txt import vtt_to_lines +from vtt2txt import split_segments, vtt_to_lines # "[prüfen: …]" in German transcripts, "[check: …]" in English ones REVIEW_MARK = re.compile(r"\[(?:prüfen|check):[^\]]*\]") @@ -30,13 +30,25 @@ WORDLISTS = { } WORDLIST_PACKAGES = {"de": "wngerman", "en": "wamerican"} MIN_SIMILARITY = 0.6 # below this a replacement counts as heavily changed -FILLERS = {"äh", "ähm", "öh", "öhm", "hm", "hmm", "uh", "uhm", "um", "er", "erm"} +# Per language: "er" and "um" are fillers in English, real words in German +FILLERS = { + "de": {"äh", "ähm", "öh", "öhm", "hm", "hmm"}, + "en": {"uh", "uhm", "um", "er", "erm", "hm", "hmm"}, +} +# Endings that turn one form of a word into another ("Punkten" -> "Punkte") +INFLECTIONS = { + "de": {"", "e", "n", "r", "s", "t", "em", "en", "er", "es", "et", "st", "te", "est", "ten"}, + "en": {"", "d", "s", "ed", "es", "ing"}, +} +UMLAUT_FOLD = str.maketrans({"ä": "e", "ö": "o", "ü": "u", "ß": "ss"}) +MIN_STEM = 3 # shortest common stem of two word forms CONTEXT_WORDS = 6 VALID_WORD = "gültiges Wort ersetzt" CHANGED_A_LOT = "stark verändert" INSERTED = "eingefügt" DELETED = "gestrichen" +WORD_FORM = "Wortform geändert" def add_token(words, token): @@ -132,10 +144,10 @@ def load_wordlist(lang): return {line.strip().lower() for line in words if line.strip()} -def glossary_words(terms, replacements): - """Normalized words of glossary terms and replacement targets.""" +def glossary_entries(terms, replacements): + """Glossary terms and replacement targets as tuples of normalized words.""" texts = list(terms) + [right for _, right in replacements] - return {normalize(word) for text in texts for word in text.split()} + return {tuple(normalize(word) for word in text.split()) for text in texts} - {()} def spelling_key(words): @@ -143,33 +155,65 @@ def spelling_key(words): return re.sub(r"[\W_]+", "", "".join(words).lower()) -def review_candidates(comparison, wordlist=None, known=()): +def similarity(old, new): + return SequenceMatcher(None, spelling_key(old), spelling_key(new)).ratio() + + +def glossary_spelling(old, new, glossary): + """True if `new` is a glossary spelling of `old`: the new words stand + together in one glossary entry and resemble the old ones. Common words of + longer entries ("finden Sie") explain nothing on their own.""" + words = tuple(normalize(word) for word in new) + size = len(words) + in_entry = any( + entry[start:start + size] == words + for entry in glossary for start in range(len(entry) - size + 1) + ) + return in_entry and similarity(old, new) >= MIN_SIMILARITY + + +def word_form_change(old, new, lang="de"): + """True if one word becomes another form of itself: only the ending + ("Punkten" -> "Punkte", "das" -> "dass") or an umlaut ("sehe" -> "sähe") + differs. "-in" is no such ending: "Professor" -> "Professorin" counts.""" + if len(old) != 1 or len(new) != 1: + return False + a, b = (NON_WORD.sub("", w).lower().translate(UMLAUT_FOLD) for w in (old[0], new[0])) + if a == b: + return True + stem = 0 + while stem < min(len(a), len(b)) and a[stem] == b[stem]: + stem += 1 + endings = INFLECTIONS.get(lang, set()) + return stem >= MIN_STEM and a[stem:] in endings and b[stem:] in endings + + +def review_candidates(comparison, wordlist=None, glossary=(), lang="de"): """Changes the model made on its own that may alter the meaning. - Not reported: changes of spacing, hyphens and punctuation only, new words - from the glossary, deleted filler words, and replacements of words not in - the word list (recognition errors) that stay similar. + Not reported: changes of spacing, hyphens and punctuation only, glossary + spellings of the old words, deleted filler words, and replacements of + words not in the word list (recognition errors) that stay similar. + Replaced real words that only change their form get their own reason. """ + fillers = FILLERS.get(lang, set()) suspects = [] for tag, i1, i2, j1, j2 in comparison.opcodes: if tag == "equal": continue old, new = comparison.raw[i1:i2], comparison.words[j1:j2] - if new and all(normalize(word) in known for word in new): - continue if tag == "delete": - if all(normalize(word) in FILLERS for word in old): + if all(normalize(word) in fillers for word in old): continue reason = DELETED elif tag == "insert": reason = INSERTED else: - old_key, new_key = spelling_key(old), spelling_key(new) - if old_key == new_key: + if spelling_key(old) == spelling_key(new) or glossary_spelling(old, new, glossary): continue if wordlist is not None and all(normalize(w) in wordlist for w in old): - reason = VALID_WORD - elif SequenceMatcher(None, old_key, new_key).ratio() < MIN_SIMILARITY: + reason = WORD_FORM if word_form_change(old, new, lang) else VALID_WORD + elif similarity(old, new) < MIN_SIMILARITY: reason = CHANGED_A_LOT else: continue @@ -205,6 +249,9 @@ del { background: var(--del); } .orig { color: var(--muted); font-size: 0.8em; } .check { background: var(--check); font-size: 0.85em; } .warn { outline: 2px solid var(--warn); outline-offset: 1px; border-radius: 2px; } +.warn.form { outline-style: dashed; outline-width: 1px; } +h3 { font-size: 1rem; margin-top: 1.5rem; } +.scroll { overflow-x: auto; } td.ctx { color: var(--muted); } td.ctx b { color: var(--fg); } """ @@ -221,28 +268,43 @@ def render_html(comparison, title): for old, new, count in summary ) suspects = comparison.suspects - suspect_rows = "\n".join( - f"{esc(s.reason)}{esc(s.old) or EMPTY}" - f"{esc(s.new) or EMPTY}" - f"{suspect_context(comparison, s)}" - for s in suspects - ) - if suspects: - suspect_table = ( - "" - f"\n{suspect_rows}\n
GrundvorherkorrigiertZusammenhang
" + important, forms = split_suspects(suspects) + + def table(rows): + body = "\n".join( + f"{esc(s.reason)}{esc(s.old) or EMPTY}" + f"{esc(s.new) or EMPTY}" + f"{suspect_context(comparison, s)}" + for s in rows ) + return ( + "
" + f"\n{body}\n
GrundvorherkorrigiertZusammenhang
" + ) + + if important: + suspect_table = table(important) + elif forms: + suspect_table = "

Keine sinnverändernden Änderungen gefunden.

" else: suspect_table = "

Keine auffälligen Änderungen gefunden.

" + if forms: + suspect_table += ( + f"\n

Wortform geändert ({len(forms)})

\n" + "

Nur Endung oder Umlaut anders („Punkten“ → „Punkte“, " + "„das“ → „dass“), meist Grammatik; ein kurzer Blick genügt.

\n" + + table(forms) + ) # Suspect words are framed; a suspect deletion shows ⚠ after the word before it warn_words, warn_after = {}, {} for s in suspects: note = esc(f"{s.reason}: „{s.old or EMPTY}“ → „{s.new or EMPTY}“", quote=True) + css = "warn form" if s.reason == WORD_FORM else "warn" if s.j1 == s.j2: warn_after.setdefault(max(s.j1 - 1, 0), []).append(note) for j in range(s.j1, s.j2): - warn_words[j] = note + warn_words[j] = (css, note) # Corrected text with its paragraphs; each word knows its paragraph parts = [] @@ -254,7 +316,8 @@ def render_html(comparison, title): current = comparison.paragraph[j] parts.append("

\n

") if j in warn_words: - piece = f"{piece}" + css, note = warn_words[j] + piece = f"{piece}" parts.append(piece) for mark in comparison.marks.get(j, []): parts.append(f"{esc(mark)}") @@ -307,6 +370,12 @@ gültige Wörter ersetzt, stark veränderte, eingefügte oder gestrichene Wörte """ +def split_suspects(suspects): + """(possible meaning changes, mere word forms), each in text order.""" + forms = [s for s in suspects if s.reason == WORD_FORM] + return [s for s in suspects if s.reason != WORD_FORM], forms + + def suspect_context(comparison, suspect): """HTML: the change in bold with a few corrected words around it.""" esc = html.escape @@ -328,15 +397,18 @@ def print_summary(comparison, limit=15, suspect_limit=10): if len(summary) > limit: print(f" … und {len(summary) - limit} weitere, siehe Bericht") - suspects = comparison.suspects - print(f"Zu prüfen: {len(suspects)} Stellen") + important, forms = split_suspects(comparison.suspects) + # Meaning changes first, word forms after them + suspects = important + forms + of_which = f" (davon {len(forms)} Wortformen)" if forms else "" + print(f"Zu prüfen: {len(suspects)} Stellen{of_which}") for s in suspects[:suspect_limit]: print(f" {s.reason}: „{s.old or EMPTY}“ → „{s.new or EMPTY}“") if len(suspects) > suspect_limit: print(f" … und {len(suspects) - suspect_limit} weitere, siehe Bericht") -def write_report(raw, corrected, target, title, model_input=None, known=(), lang="de"): +def write_report(raw, corrected, target, title, model_input=None, glossary=(), lang="de"): """Write the HTML report; return the comparison with the suspect changes. model_input is the text the model got (raw text after glossary @@ -344,7 +416,7 @@ def write_report(raw, corrected, target, title, model_input=None, known=(), lang """ comparison = compare(raw, corrected) by_model = compare(raw if model_input is None else model_input, corrected) - comparison.suspects = review_candidates(by_model, load_wordlist(lang), set(known)) + comparison.suspects = review_candidates(by_model, load_wordlist(lang), glossary, lang) target.write_text(render_html(comparison, title), encoding="utf-8") return comparison @@ -355,6 +427,11 @@ def report_path(corrected_path): return corrected_path.with_name(f"{stem}.aenderungen.html") +def without_headers(text): + """Text without time headers ("[00:04:57 - 00:06:04]") of excerpts.""" + return "\n\n".join(body for _, body in split_segments(text)) + + def read_raw(path): text = path.read_text(encoding="utf-8-sig") if path.suffix.lower() == ".vtt": @@ -397,6 +474,7 @@ def parse_args(): def main(): # abschrift_korrigieren imports this module: import it only when needed from abschrift_korrigieren import apply_replacements, read_glossary + from yt_untertitel import base_language args = parse_args() raw = read_raw(args.roh) @@ -409,10 +487,13 @@ def main(): model_input = apply_replacements(" ".join(raw.split()), replacements) corrected = args.korrigiert.read_text(encoding="utf-8") + # A raw .vtt has no time headers: those of the excerpts are no insertions + if without_headers(raw) == raw.strip(): + corrected = without_headers(corrected) comparison = write_report( raw, corrected, args.output, args.korrigiert.name, - model_input=model_input, known=glossary_words(terms, replacements), - lang=args.lang, + model_input=model_input, glossary=glossary_entries(terms, replacements), + lang=base_language(args.lang), ) print_summary(comparison) print(f"Bericht: {args.output}") diff --git a/tests/daten/beispiel.de.txt b/tests/daten/beispiel.de.txt new file mode 100644 index 0000000..967d396 --- /dev/null +++ b/tests/daten/beispiel.de.txt @@ -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] diff --git a/tests/daten/beispiel.de.vtt b/tests/daten/beispiel.de.vtt new file mode 100644 index 0000000..961c26a --- /dev/null +++ b/tests/daten/beispiel.de.vtt @@ -0,0 +1,2683 @@ +WEBVTT +Kind: captions +Language: de + +00:00:00.500 --> 00:00:03.490 align:start position:0% + +[applaus] + +00:00:03.490 --> 00:00:03.500 align:start position:0% +[applaus] + + +00:00:03.500 --> 00:00:05.490 align:start position:0% +[applaus] +Vielen<00:00:03.900> Dank.<00:00:04.300> Liebe<00:00:04.700> Gäste,<00:00:05.100> liebe + +00:00:05.490 --> 00:00:05.500 align:start position:0% +Vielen Dank. Liebe Gäste, liebe + + +00:00:05.500 --> 00:00:08.290 align:start position:0% +Vielen Dank. Liebe Gäste, liebe +Bürgerinnen<00:00:05.900> und<00:00:06.300> Bürger<00:00:06.700> von<00:00:07.100> Auen<00:00:07.500> Tal,<00:00:07.900> ich + +00:00:08.290 --> 00:00:08.300 align:start position:0% +Bürgerinnen und Bürger von Auen Tal, ich + + +00:00:08.300 --> 00:00:10.690 align:start position:0% +Bürgerinnen und Bürger von Auen Tal, ich +freue<00:00:08.700> mich<00:00:09.100> sehr,<00:00:09.500> dass<00:00:09.900> Sie<00:00:10.300> heute + +00:00:10.690 --> 00:00:10.700 align:start position:0% +freue mich sehr, dass Sie heute + + +00:00:10.700 --> 00:00:13.890 align:start position:0% +freue mich sehr, dass Sie heute +so<00:00:11.100> zahlreich<00:00:11.500> gekommen<00:00:11.900> sind.<00:00:12.300> Wir<00:00:12.700> feiern<00:00:13.100> ein<00:00:13.500> besonderes + +00:00:13.890 --> 00:00:13.900 align:start position:0% +so zahlreich gekommen sind. Wir feiern ein besonderes + + +00:00:13.900 --> 00:00:16.290 align:start position:0% +so zahlreich gekommen sind. Wir feiern ein besonderes +Jubiläum.<00:00:14.300> Vor<00:00:14.700> 750<00:00:15.100> Jahren<00:00:15.500> wurde<00:00:15.900> unser + +00:00:16.290 --> 00:00:16.300 align:start position:0% +Jubiläum. Vor 750 Jahren wurde unser + + +00:00:16.300 --> 00:00:17.890 align:start position:0% +Jubiläum. Vor 750 Jahren wurde unser +Ort<00:00:16.700> zum<00:00:17.100> ersten<00:00:17.500> Mal + +00:00:17.890 --> 00:00:17.900 align:start position:0% +Ort zum ersten Mal + + +00:00:17.900 --> 00:00:20.690 align:start position:0% +Ort zum ersten Mal +in<00:00:18.300> einer<00:00:18.700> Urkunde<00:00:19.100> erwähnt.<00:00:19.500> Das<00:00:19.900> war<00:00:20.300> im + +00:00:20.690 --> 00:00:20.700 align:start position:0% +in einer Urkunde erwähnt. Das war im + + +00:00:20.700 --> 00:00:23.090 align:start position:0% +in einer Urkunde erwähnt. Das war im +Jahr<00:00:21.100> 12<00:00:21.500> 74.<00:00:21.900> Damals<00:00:22.300> war<00:00:22.700> Auen + +00:00:23.090 --> 00:00:23.100 align:start position:0% +Jahr 12 74. Damals war Auen + + +00:00:23.100 --> 00:00:25.090 align:start position:0% +Jahr 12 74. Damals war Auen +Tal<00:00:23.500> ein<00:00:23.900> kleiner<00:00:24.300> Weiler<00:00:24.700> mit + +00:00:25.090 --> 00:00:25.100 align:start position:0% +Tal ein kleiner Weiler mit + + +00:00:25.100 --> 00:00:27.890 align:start position:0% +Tal ein kleiner Weiler mit +drei<00:00:25.500> Höfen<00:00:25.900> und<00:00:26.300> einer<00:00:26.700> Mühle<00:00:27.100> am<00:00:27.500> Bach. + +00:00:27.890 --> 00:00:27.900 align:start position:0% +drei Höfen und einer Mühle am Bach. + + +00:00:27.900 --> 00:00:30.290 align:start position:0% +drei Höfen und einer Mühle am Bach. +Heute<00:00:28.300> leben<00:00:28.700> hier<00:00:29.100> fast<00:00:29.500> viertausend<00:00:29.900> Menschen. + +00:00:30.290 --> 00:00:30.300 align:start position:0% +Heute leben hier fast viertausend Menschen. + + +00:00:30.300 --> 00:00:33.290 align:start position:0% +Heute leben hier fast viertausend Menschen. +[applaus] + +00:00:33.290 --> 00:00:33.300 align:start position:0% +[applaus] + + +00:00:33.300 --> 00:00:36.490 align:start position:0% +[applaus] +Ich<00:00:33.700> möchte<00:00:34.100> Ihnen<00:00:34.500> heute<00:00:34.900> keine<00:00:35.300> lange<00:00:35.700> Geschichtsstunde<00:00:36.100> halten. + +00:00:36.490 --> 00:00:36.500 align:start position:0% +Ich möchte Ihnen heute keine lange Geschichtsstunde halten. + + +00:00:36.500 --> 00:00:38.890 align:start position:0% +Ich möchte Ihnen heute keine lange Geschichtsstunde halten. +Dafür<00:00:36.900> haben<00:00:37.300> wir<00:00:37.700> Frau<00:00:38.100> Dr.<00:00:38.500> Jorinde + +00:00:38.890 --> 00:00:38.900 align:start position:0% +Dafür haben wir Frau Dr. Jorinde + + +00:00:38.900 --> 00:00:40.490 align:start position:0% +Dafür haben wir Frau Dr. Jorinde +Haber<00:00:39.300> Kamp<00:00:39.700> vom<00:00:40.100> Kreisarchiv + +00:00:40.490 --> 00:00:40.500 align:start position:0% +Haber Kamp vom Kreisarchiv + + +00:00:40.500 --> 00:00:43.290 align:start position:0% +Haber Kamp vom Kreisarchiv +eingeladen,<00:00:40.900> die<00:00:41.300> gleich<00:00:41.700> noch<00:00:42.100> zu<00:00:42.500> Ihnen<00:00:42.900> sprechen + +00:00:43.290 --> 00:00:43.300 align:start position:0% +eingeladen, die gleich noch zu Ihnen sprechen + + +00:00:43.300 --> 00:00:45.690 align:start position:0% +eingeladen, die gleich noch zu Ihnen sprechen +wird.<00:00:43.700> Ich<00:00:44.100> möchte<00:00:44.500> lieber<00:00:44.900> erzählen,<00:00:45.300> was + +00:00:45.690 --> 00:00:45.700 align:start position:0% +wird. Ich möchte lieber erzählen, was + + +00:00:45.700 --> 00:00:47.690 align:start position:0% +wird. Ich möchte lieber erzählen, was +dieser<00:00:46.100> Ort<00:00:46.500> für<00:00:46.900> uns<00:00:47.300> bedeutet. + +00:00:47.690 --> 00:00:47.700 align:start position:0% +dieser Ort für uns bedeutet. + + +00:00:47.700 --> 00:00:50.490 align:start position:0% +dieser Ort für uns bedeutet. +Und<00:00:48.100> ich<00:00:48.500> möchte<00:00:48.900> erzählen,<00:00:49.300> was<00:00:49.700> wir<00:00:50.100> in + +00:00:50.490 --> 00:00:50.500 align:start position:0% +Und ich möchte erzählen, was wir in + + +00:00:50.500 --> 00:00:52.090 align:start position:0% +Und ich möchte erzählen, was wir in +den<00:00:50.900> nächsten<00:00:51.300> Jahren<00:00:51.700> vorhaben. + +00:00:52.090 --> 00:00:52.100 align:start position:0% +den nächsten Jahren vorhaben. + + +00:00:52.100 --> 00:00:55.290 align:start position:0% +den nächsten Jahren vorhaben. +Fangen<00:00:52.500> wir<00:00:52.900> mit<00:00:53.300> der<00:00:53.700> Mühle<00:00:54.100> an.<00:00:54.500> Die<00:00:54.900> alte + +00:00:55.290 --> 00:00:55.300 align:start position:0% +Fangen wir mit der Mühle an. Die alte + + +00:00:55.300 --> 00:00:57.690 align:start position:0% +Fangen wir mit der Mühle an. Die alte +Mühle<00:00:55.700> am<00:00:56.100> Linden<00:00:56.500> Bach<00:00:56.900> steht<00:00:57.300> noch + +00:00:57.690 --> 00:00:57.700 align:start position:0% +Mühle am Linden Bach steht noch + + +00:00:57.700 --> 00:00:59.290 align:start position:0% +Mühle am Linden Bach steht noch +heute.<00:00:58.100> Sie<00:00:58.500> hat<00:00:58.900> viele + +00:00:59.290 --> 00:00:59.300 align:start position:0% +heute. Sie hat viele + + +00:00:59.300 --> 00:01:02.090 align:start position:0% +heute. Sie hat viele +Besitzer<00:00:59.700> gehabt.<00:01:00.100> Sie<00:01:00.500> ist<00:01:00.900> zweimal<00:01:01.300> abgebrannt<00:01:01.700> und + +00:01:02.090 --> 00:01:02.100 align:start position:0% +Besitzer gehabt. Sie ist zweimal abgebrannt und + + +00:01:02.100 --> 00:01:04.490 align:start position:0% +Besitzer gehabt. Sie ist zweimal abgebrannt und +zweimal<00:01:02.500> wieder<00:01:02.900> aufgebaut<00:01:03.300> worden.<00:01:03.700> Seit<00:01:04.100> dem + +00:01:04.490 --> 00:01:04.500 align:start position:0% +zweimal wieder aufgebaut worden. Seit dem + + +00:01:04.500 --> 00:01:06.490 align:start position:0% +zweimal wieder aufgebaut worden. Seit dem +3.<00:01:04.900> Oktober<00:01:05.300> 1990<00:01:05.700> gehört<00:01:06.100> sie + +00:01:06.490 --> 00:01:06.500 align:start position:0% +3. Oktober 1990 gehört sie + + +00:01:06.500 --> 00:01:09.290 align:start position:0% +3. Oktober 1990 gehört sie +der<00:01:06.900> Gemeinde.<00:01:07.300> Viele<00:01:07.700> von<00:01:08.100> Ihnen<00:01:08.500> kennen<00:01:08.900> sie + +00:01:09.290 --> 00:01:09.300 align:start position:0% +der Gemeinde. Viele von Ihnen kennen sie + + +00:01:09.300 --> 00:01:11.690 align:start position:0% +der Gemeinde. Viele von Ihnen kennen sie +als<00:01:09.700> Heimatmuseum.<00:01:10.100> Manche<00:01:10.500> kennen<00:01:10.900> sie<00:01:11.300> auch + +00:01:11.690 --> 00:01:11.700 align:start position:0% +als Heimatmuseum. Manche kennen sie auch + + +00:01:11.700 --> 00:01:14.890 align:start position:0% +als Heimatmuseum. Manche kennen sie auch +als<00:01:12.100> den<00:01:12.500> Ort,<00:01:12.900> an<00:01:13.300> dem<00:01:13.700> sie<00:01:14.100> ihren<00:01:14.500> ersten + +00:01:14.890 --> 00:01:14.900 align:start position:0% +als den Ort, an dem sie ihren ersten + + +00:01:14.900 --> 00:01:17.290 align:start position:0% +als den Ort, an dem sie ihren ersten +Kuss<00:01:15.300> bekommen<00:01:15.700> haben.<00:01:16.100> Ich<00:01:16.500> nenne<00:01:16.900> keine + +00:01:17.290 --> 00:01:17.300 align:start position:0% +Kuss bekommen haben. Ich nenne keine + + +00:01:17.300 --> 00:01:17.690 align:start position:0% +Kuss bekommen haben. Ich nenne keine +Namen. + +00:01:17.690 --> 00:01:17.700 align:start position:0% +Namen. + + +00:01:17.700 --> 00:01:20.690 align:start position:0% +Namen. +[lachen] + +00:01:20.690 --> 00:01:20.700 align:start position:0% +[lachen] + + +00:01:20.700 --> 00:01:23.490 align:start position:0% +[lachen] +Die<00:01:21.100> Mühle<00:01:21.500> ist<00:01:21.900> ein<00:01:22.300> gutes<00:01:22.700> Beispiel<00:01:23.100> für + +00:01:23.490 --> 00:01:23.500 align:start position:0% +Die Mühle ist ein gutes Beispiel für + + +00:01:23.500 --> 00:01:25.890 align:start position:0% +Die Mühle ist ein gutes Beispiel für +das,<00:01:23.900> was<00:01:24.300> Auen<00:01:24.700> Tal<00:01:25.100> ausmacht.<00:01:25.500> Wir + +00:01:25.890 --> 00:01:25.900 align:start position:0% +das, was Auen Tal ausmacht. Wir + + +00:01:25.900 --> 00:01:27.890 align:start position:0% +das, was Auen Tal ausmacht. Wir +bauen<00:01:26.300> wieder<00:01:26.700> auf,<00:01:27.100> wenn<00:01:27.500> etwas + +00:01:27.890 --> 00:01:27.900 align:start position:0% +bauen wieder auf, wenn etwas + + +00:01:27.900 --> 00:01:30.690 align:start position:0% +bauen wieder auf, wenn etwas +kaputtgeht.<00:01:28.300> Wir<00:01:28.700> geben<00:01:29.100> nicht<00:01:29.500> auf.<00:01:29.900> Und<00:01:30.300> wir + +00:01:30.690 --> 00:01:30.700 align:start position:0% +kaputtgeht. Wir geben nicht auf. Und wir + + +00:01:30.700 --> 00:01:33.090 align:start position:0% +kaputtgeht. Wir geben nicht auf. Und wir +machen<00:01:31.100> das<00:01:31.500> gemeinsam.<00:01:31.900> Das<00:01:32.300> klingt<00:01:32.700> vielleicht + +00:01:33.090 --> 00:01:33.100 align:start position:0% +machen das gemeinsam. Das klingt vielleicht + + +00:01:33.100 --> 00:01:36.290 align:start position:0% +machen das gemeinsam. Das klingt vielleicht +nach<00:01:33.500> einer<00:01:33.900> Floskel.<00:01:34.300> Aber<00:01:34.700> ich<00:01:35.100> habe<00:01:35.500> es<00:01:35.900> selbst + +00:01:36.290 --> 00:01:36.300 align:start position:0% +nach einer Floskel. Aber ich habe es selbst + + +00:01:36.300 --> 00:01:38.690 align:start position:0% +nach einer Floskel. Aber ich habe es selbst +erlebt.<00:01:36.700> Als<00:01:37.100> vor<00:01:37.500> zwölf<00:01:37.900> Jahren<00:01:38.300> das + +00:01:38.690 --> 00:01:38.700 align:start position:0% +erlebt. Als vor zwölf Jahren das + + +00:01:38.700 --> 00:01:40.290 align:start position:0% +erlebt. Als vor zwölf Jahren das +Hochwasser<00:01:39.100> kam,<00:01:39.500> standen<00:01:39.900> am + +00:01:40.290 --> 00:01:40.300 align:start position:0% +Hochwasser kam, standen am + + +00:01:40.300 --> 00:01:43.090 align:start position:0% +Hochwasser kam, standen am +nächsten<00:01:40.700> Morgen<00:01:41.100> über<00:01:41.500> zweihundert<00:01:41.900> Menschen<00:01:42.300> mit<00:01:42.700> Schaufeln + +00:01:43.090 --> 00:01:43.100 align:start position:0% +nächsten Morgen über zweihundert Menschen mit Schaufeln + + +00:01:43.100 --> 00:01:45.490 align:start position:0% +nächsten Morgen über zweihundert Menschen mit Schaufeln +und<00:01:43.500> Eimern<00:01:43.900> vor<00:01:44.300> dem<00:01:44.700> Rathaus.<00:01:45.100> Niemand + +00:01:45.490 --> 00:01:45.500 align:start position:0% +und Eimern vor dem Rathaus. Niemand + + +00:01:45.500 --> 00:01:47.490 align:start position:0% +und Eimern vor dem Rathaus. Niemand +hatte<00:01:45.900> sie<00:01:46.300> gerufen.<00:01:46.700> Sie<00:01:47.100> waren + +00:01:47.490 --> 00:01:47.500 align:start position:0% +hatte sie gerufen. Sie waren + + +00:01:47.500 --> 00:01:48.290 align:start position:0% +hatte sie gerufen. Sie waren +einfach<00:01:47.900> da. + +00:01:48.290 --> 00:01:48.300 align:start position:0% +einfach da. + + +00:01:48.300 --> 00:01:50.690 align:start position:0% +einfach da. +Ich<00:01:48.700> erinnere<00:01:49.100> mich<00:01:49.500> an<00:01:49.900> eine<00:01:50.300> ältere + +00:01:50.690 --> 00:01:50.700 align:start position:0% +Ich erinnere mich an eine ältere + + +00:01:50.700 --> 00:01:53.890 align:start position:0% +Ich erinnere mich an eine ältere +Dame<00:01:51.100> aus<00:01:51.500> der<00:01:51.900> Bachstraße.<00:01:52.300> Ihr<00:01:52.700> Keller<00:01:53.100> stand<00:01:53.500> bis + +00:01:53.890 --> 00:01:53.900 align:start position:0% +Dame aus der Bachstraße. Ihr Keller stand bis + + +00:01:53.900 --> 00:01:56.290 align:start position:0% +Dame aus der Bachstraße. Ihr Keller stand bis +zur<00:01:54.300> Decke<00:01:54.700> unter<00:01:55.100> Wasser.<00:01:55.500> Sie<00:01:55.900> hat + +00:01:56.290 --> 00:01:56.300 align:start position:0% +zur Decke unter Wasser. Sie hat + + +00:01:56.300 --> 00:01:57.890 align:start position:0% +zur Decke unter Wasser. Sie hat +trotzdem<00:01:56.700> für<00:01:57.100> alle<00:01:57.500> Helfer + +00:01:57.890 --> 00:01:57.900 align:start position:0% +trotzdem für alle Helfer + + +00:01:57.900 --> 00:02:00.690 align:start position:0% +trotzdem für alle Helfer +Kaffee<00:01:58.300> gekocht.<00:01:58.700> Sie<00:01:59.100> hat<00:01:59.500> gesagt,<00:01:59.900> das<00:02:00.300> Wasser + +00:02:00.690 --> 00:02:00.700 align:start position:0% +Kaffee gekocht. Sie hat gesagt, das Wasser + + +00:02:00.700 --> 00:02:03.090 align:start position:0% +Kaffee gekocht. Sie hat gesagt, das Wasser +geht<00:02:01.100> wieder,<00:02:01.500> aber<00:02:01.900> die<00:02:02.300> Nachbarn<00:02:02.700> bleiben. + +00:02:03.090 --> 00:02:03.100 align:start position:0% +geht wieder, aber die Nachbarn bleiben. + + +00:02:03.100 --> 00:02:05.090 align:start position:0% +geht wieder, aber die Nachbarn bleiben. +Diesen<00:02:03.500> Satz<00:02:03.900> habe<00:02:04.300> ich<00:02:04.700> mir + +00:02:05.090 --> 00:02:05.100 align:start position:0% +Diesen Satz habe ich mir + + +00:02:05.100 --> 00:02:07.890 align:start position:0% +Diesen Satz habe ich mir +gemerkt.<00:02:05.500> Er<00:02:05.900> hängt<00:02:06.300> heute<00:02:06.700> als<00:02:07.100> Spruch<00:02:07.500> in + +00:02:07.890 --> 00:02:07.900 align:start position:0% +gemerkt. Er hängt heute als Spruch in + + +00:02:07.900 --> 00:02:08.690 align:start position:0% +gemerkt. Er hängt heute als Spruch in +meinem<00:02:08.300> Büro. + +00:02:08.690 --> 00:02:08.700 align:start position:0% +meinem Büro. + + +00:02:08.700 --> 00:02:11.890 align:start position:0% +meinem Büro. +Liebe<00:02:09.100> Gäste,<00:02:09.500> ein<00:02:09.900> Jubiläum<00:02:10.300> ist<00:02:10.700> ein<00:02:11.100> guter<00:02:11.500> Anlass, + +00:02:11.890 --> 00:02:11.900 align:start position:0% +Liebe Gäste, ein Jubiläum ist ein guter Anlass, + + +00:02:11.900 --> 00:02:14.290 align:start position:0% +Liebe Gäste, ein Jubiläum ist ein guter Anlass, +um<00:02:12.300> zurückzuschauen.<00:02:12.700> Es<00:02:13.100> ist<00:02:13.500> aber<00:02:13.900> auch + +00:02:14.290 --> 00:02:14.300 align:start position:0% +um zurückzuschauen. Es ist aber auch + + +00:02:14.300 --> 00:02:15.890 align:start position:0% +um zurückzuschauen. Es ist aber auch +ein<00:02:14.700> guter<00:02:15.100> Anlass,<00:02:15.500> um + +00:02:15.890 --> 00:02:15.900 align:start position:0% +ein guter Anlass, um + + +00:02:15.900 --> 00:02:18.690 align:start position:0% +ein guter Anlass, um +nach<00:02:16.300> vorn<00:02:16.700> zu<00:02:17.100> schauen.<00:02:17.500> Und<00:02:17.900> da<00:02:18.300> gibt + +00:02:18.690 --> 00:02:18.700 align:start position:0% +nach vorn zu schauen. Und da gibt + + +00:02:18.700 --> 00:02:21.090 align:start position:0% +nach vorn zu schauen. Und da gibt +es<00:02:19.100> einiges<00:02:19.500> zu<00:02:19.900> tun.<00:02:20.300> Ich<00:02:20.700> will + +00:02:21.090 --> 00:02:21.100 align:start position:0% +es einiges zu tun. Ich will + + +00:02:21.100 --> 00:02:23.090 align:start position:0% +es einiges zu tun. Ich will +Ihnen<00:02:21.500> drei<00:02:21.900> Dinge<00:02:22.300> nennen,<00:02:22.700> die + +00:02:23.090 --> 00:02:23.100 align:start position:0% +Ihnen drei Dinge nennen, die + + +00:02:23.100 --> 00:02:25.890 align:start position:0% +Ihnen drei Dinge nennen, die +uns<00:02:23.500> in<00:02:23.900> den<00:02:24.300> nächsten<00:02:24.700> Jahren<00:02:25.100> beschäftigen<00:02:25.500> werden. + +00:02:25.890 --> 00:02:25.900 align:start position:0% +uns in den nächsten Jahren beschäftigen werden. + + +00:02:25.900 --> 00:02:28.290 align:start position:0% +uns in den nächsten Jahren beschäftigen werden. +Das<00:02:26.300> erste<00:02:26.700> ist<00:02:27.100> die<00:02:27.500> Schule.<00:02:27.900> Unsere + +00:02:28.290 --> 00:02:28.300 align:start position:0% +Das erste ist die Schule. Unsere + + +00:02:28.300 --> 00:02:31.490 align:start position:0% +Das erste ist die Schule. Unsere +Grundschule<00:02:28.700> ist<00:02:29.100> über<00:02:29.500> hundert<00:02:29.900> Jahre<00:02:30.300> alt.<00:02:30.700> Das<00:02:31.100> Gebäude + +00:02:31.490 --> 00:02:31.500 align:start position:0% +Grundschule ist über hundert Jahre alt. Das Gebäude + + +00:02:31.500 --> 00:02:33.890 align:start position:0% +Grundschule ist über hundert Jahre alt. Das Gebäude +ist<00:02:31.900> schön,<00:02:32.300> aber<00:02:32.700> es<00:02:33.100> ist<00:02:33.500> zu + +00:02:33.890 --> 00:02:33.900 align:start position:0% +ist schön, aber es ist zu + + +00:02:33.900 --> 00:02:35.490 align:start position:0% +ist schön, aber es ist zu +klein<00:02:34.300> geworden.<00:02:34.700> Wir<00:02:35.100> haben + +00:02:35.490 --> 00:02:35.500 align:start position:0% +klein geworden. Wir haben + + +00:02:35.500 --> 00:02:38.290 align:start position:0% +klein geworden. Wir haben +im<00:02:35.900> letzten<00:02:36.300> Jahr<00:02:36.700> so<00:02:37.100> viele<00:02:37.500> Kinder<00:02:37.900> eingeschult + +00:02:38.290 --> 00:02:38.300 align:start position:0% +im letzten Jahr so viele Kinder eingeschult + + +00:02:38.300 --> 00:02:40.690 align:start position:0% +im letzten Jahr so viele Kinder eingeschult +wie<00:02:38.700> seit<00:02:39.100> Jahrzehnten<00:02:39.500> nicht<00:02:39.900> mehr.<00:02:40.300> Das + +00:02:40.690 --> 00:02:40.700 align:start position:0% +wie seit Jahrzehnten nicht mehr. Das + + +00:02:40.700 --> 00:02:42.690 align:start position:0% +wie seit Jahrzehnten nicht mehr. Das +ist<00:02:41.100> eine<00:02:41.500> gute<00:02:41.900> Nachricht.<00:02:42.300> Es + +00:02:42.690 --> 00:02:42.700 align:start position:0% +ist eine gute Nachricht. Es + + +00:02:42.700 --> 00:02:45.490 align:start position:0% +ist eine gute Nachricht. Es +bedeutet<00:02:43.100> aber<00:02:43.500> auch,<00:02:43.900> dass<00:02:44.300> wir<00:02:44.700> anbauen<00:02:45.100> müssen. + +00:02:45.490 --> 00:02:45.500 align:start position:0% +bedeutet aber auch, dass wir anbauen müssen. + + +00:02:45.500 --> 00:02:47.890 align:start position:0% +bedeutet aber auch, dass wir anbauen müssen. +Der<00:02:45.900> Gemeinderat<00:02:46.300> hat<00:02:46.700> den<00:02:47.100> Anbau<00:02:47.500> im + +00:02:47.890 --> 00:02:47.900 align:start position:0% +Der Gemeinderat hat den Anbau im + + +00:02:47.900 --> 00:02:51.090 align:start position:0% +Der Gemeinderat hat den Anbau im +Frühjahr<00:02:48.300> beschlossen.<00:02:48.700> Die<00:02:49.100> Bauarbeiten<00:02:49.500> beginnen<00:02:49.900> im<00:02:50.300> nächsten<00:02:50.700> Sommer. + +00:02:51.090 --> 00:02:51.100 align:start position:0% +Frühjahr beschlossen. Die Bauarbeiten beginnen im nächsten Sommer. + + +00:02:51.100 --> 00:02:53.490 align:start position:0% +Frühjahr beschlossen. Die Bauarbeiten beginnen im nächsten Sommer. +Wenn<00:02:51.500> alles<00:02:51.900> gut<00:02:52.300> geht,<00:02:52.700> ziehen<00:02:53.100> die + +00:02:53.490 --> 00:02:53.500 align:start position:0% +Wenn alles gut geht, ziehen die + + +00:02:53.500 --> 00:02:55.090 align:start position:0% +Wenn alles gut geht, ziehen die +Kinder<00:02:53.900> in<00:02:54.300> zwei<00:02:54.700> Jahren + +00:02:55.090 --> 00:02:55.100 align:start position:0% +Kinder in zwei Jahren + + +00:02:55.100 --> 00:02:56.690 align:start position:0% +Kinder in zwei Jahren +in<00:02:55.500> die<00:02:55.900> neuen<00:02:56.300> Räume. + +00:02:56.690 --> 00:02:56.700 align:start position:0% +in die neuen Räume. + + +00:02:56.700 --> 00:02:59.090 align:start position:0% +in die neuen Räume. +Das<00:02:57.100> zweite<00:02:57.500> ist<00:02:57.900> der<00:02:58.300> Verkehr.<00:02:58.700> Viele + +00:02:59.090 --> 00:02:59.100 align:start position:0% +Das zweite ist der Verkehr. Viele + + +00:02:59.100 --> 00:03:01.090 align:start position:0% +Das zweite ist der Verkehr. Viele +von<00:02:59.500> Ihnen<00:02:59.900> ärgern<00:03:00.300> sich<00:03:00.700> über + +00:03:01.090 --> 00:03:01.100 align:start position:0% +von Ihnen ärgern sich über + + +00:03:01.100 --> 00:03:03.890 align:start position:0% +von Ihnen ärgern sich über +die<00:03:01.500> Lastwagen,<00:03:01.900> die<00:03:02.300> durch<00:03:02.700> die<00:03:03.100> Hauptstraße<00:03:03.500> fahren. + +00:03:03.890 --> 00:03:03.900 align:start position:0% +die Lastwagen, die durch die Hauptstraße fahren. + + +00:03:03.900 --> 00:03:06.290 align:start position:0% +die Lastwagen, die durch die Hauptstraße fahren. +Ich<00:03:04.300> ärgere<00:03:04.700> mich<00:03:05.100> auch.<00:03:05.500> Seit<00:03:05.900> Jahren + +00:03:06.290 --> 00:03:06.300 align:start position:0% +Ich ärgere mich auch. Seit Jahren + + +00:03:06.300 --> 00:03:09.490 align:start position:0% +Ich ärgere mich auch. Seit Jahren +reden<00:03:06.700> wir<00:03:07.100> über<00:03:07.500> eine<00:03:07.900> Umgehungsstraße.<00:03:08.300> Seit<00:03:08.700> Jahren<00:03:09.100> passiert + +00:03:09.490 --> 00:03:09.500 align:start position:0% +reden wir über eine Umgehungsstraße. Seit Jahren passiert + + +00:03:09.500 --> 00:03:11.890 align:start position:0% +reden wir über eine Umgehungsstraße. Seit Jahren passiert +wenig.<00:03:09.900> Ich<00:03:10.300> will<00:03:10.700> Ihnen<00:03:11.100> nichts<00:03:11.500> versprechen, + +00:03:11.890 --> 00:03:11.900 align:start position:0% +wenig. Ich will Ihnen nichts versprechen, + + +00:03:11.900 --> 00:03:13.490 align:start position:0% +wenig. Ich will Ihnen nichts versprechen, +was<00:03:12.300> ich<00:03:12.700> nicht<00:03:13.100> halten + +00:03:13.490 --> 00:03:13.500 align:start position:0% +was ich nicht halten + + +00:03:13.500 --> 00:03:16.290 align:start position:0% +was ich nicht halten +kann.<00:03:13.900> Aber<00:03:14.300> ich<00:03:14.700> kann<00:03:15.100> Ihnen<00:03:15.500> sagen,<00:03:15.900> dass + +00:03:16.290 --> 00:03:16.300 align:start position:0% +kann. Aber ich kann Ihnen sagen, dass + + +00:03:16.300 --> 00:03:18.690 align:start position:0% +kann. Aber ich kann Ihnen sagen, dass +das<00:03:16.700> Land<00:03:17.100> die<00:03:17.500> Planung<00:03:17.900> jetzt<00:03:18.300> endlich + +00:03:18.690 --> 00:03:18.700 align:start position:0% +das Land die Planung jetzt endlich + + +00:03:18.700 --> 00:03:20.690 align:start position:0% +das Land die Planung jetzt endlich +aufgenommen<00:03:19.100> hat.<00:03:19.500> Das<00:03:19.900> ist<00:03:20.300> ein + +00:03:20.690 --> 00:03:20.700 align:start position:0% +aufgenommen hat. Das ist ein + + +00:03:20.700 --> 00:03:23.490 align:start position:0% +aufgenommen hat. Das ist ein +erster<00:03:21.100> Schritt.<00:03:21.500> Es<00:03:21.900> werden<00:03:22.300> noch<00:03:22.700> viele<00:03:23.100> Schritte + +00:03:23.490 --> 00:03:23.500 align:start position:0% +erster Schritt. Es werden noch viele Schritte + + +00:03:23.500 --> 00:03:24.290 align:start position:0% +erster Schritt. Es werden noch viele Schritte +folgen<00:03:23.900> müssen. + +00:03:24.290 --> 00:03:24.300 align:start position:0% +folgen müssen. + + +00:03:24.300 --> 00:03:27.490 align:start position:0% +folgen müssen. +Das<00:03:24.700> dritte<00:03:25.100> ist<00:03:25.500> die<00:03:25.900> Nahversorgung.<00:03:26.300> Seit<00:03:26.700> der<00:03:27.100> Bäcker + +00:03:27.490 --> 00:03:27.500 align:start position:0% +Das dritte ist die Nahversorgung. Seit der Bäcker + + +00:03:27.500 --> 00:03:29.890 align:start position:0% +Das dritte ist die Nahversorgung. Seit der Bäcker +an<00:03:27.900> der<00:03:28.300> Kirche<00:03:28.700> geschlossen<00:03:29.100> hat,<00:03:29.500> gibt + +00:03:29.890 --> 00:03:29.900 align:start position:0% +an der Kirche geschlossen hat, gibt + + +00:03:29.900 --> 00:03:31.490 align:start position:0% +an der Kirche geschlossen hat, gibt +es<00:03:30.300> im<00:03:30.700> Ortskern<00:03:31.100> kein + +00:03:31.490 --> 00:03:31.500 align:start position:0% +es im Ortskern kein + + +00:03:31.500 --> 00:03:34.290 align:start position:0% +es im Ortskern kein +Geschäft<00:03:31.900> mehr.<00:03:32.300> Wer<00:03:32.700> kein<00:03:33.100> Auto<00:03:33.500> hat,<00:03:33.900> muss + +00:03:34.290 --> 00:03:34.300 align:start position:0% +Geschäft mehr. Wer kein Auto hat, muss + + +00:03:34.300 --> 00:03:36.690 align:start position:0% +Geschäft mehr. Wer kein Auto hat, muss +mit<00:03:34.700> dem<00:03:35.100> Bus<00:03:35.500> nach<00:03:35.900> Linden<00:03:36.300> Brunn + +00:03:36.690 --> 00:03:36.700 align:start position:0% +mit dem Bus nach Linden Brunn + + +00:03:36.700 --> 00:03:38.690 align:start position:0% +mit dem Bus nach Linden Brunn +fahren.<00:03:37.100> Das<00:03:37.500> ist<00:03:37.900> für<00:03:38.300> viele + +00:03:38.690 --> 00:03:38.700 align:start position:0% +fahren. Das ist für viele + + +00:03:38.700 --> 00:03:41.490 align:start position:0% +fahren. Das ist für viele +ältere<00:03:39.100> Menschen<00:03:39.500> ein<00:03:39.900> Problem.<00:03:40.300> Wir<00:03:40.700> haben<00:03:41.100> deshalb + +00:03:41.490 --> 00:03:41.500 align:start position:0% +ältere Menschen ein Problem. Wir haben deshalb + + +00:03:41.500 --> 00:03:43.890 align:start position:0% +ältere Menschen ein Problem. Wir haben deshalb +mit<00:03:41.900> einer<00:03:42.300> Genossenschaft<00:03:42.700> gesprochen,<00:03:43.100> die<00:03:43.500> Dorfläden + +00:03:43.890 --> 00:03:43.900 align:start position:0% +mit einer Genossenschaft gesprochen, die Dorfläden + + +00:03:43.900 --> 00:03:47.090 align:start position:0% +mit einer Genossenschaft gesprochen, die Dorfläden +betreibt.<00:03:44.300> Die<00:03:44.700> Gespräche<00:03:45.100> sind<00:03:45.500> gut<00:03:45.900> gelaufen.<00:03:46.300> Ich<00:03:46.700> hoffe, + +00:03:47.090 --> 00:03:47.100 align:start position:0% +betreibt. Die Gespräche sind gut gelaufen. Ich hoffe, + + +00:03:47.100 --> 00:03:49.490 align:start position:0% +betreibt. Die Gespräche sind gut gelaufen. Ich hoffe, +dass<00:03:47.500> wir<00:03:47.900> Ihnen<00:03:48.300> im<00:03:48.700> Herbst<00:03:49.100> mehr + +00:03:49.490 --> 00:03:49.500 align:start position:0% +dass wir Ihnen im Herbst mehr + + +00:03:49.500 --> 00:03:50.690 align:start position:0% +dass wir Ihnen im Herbst mehr +dazu<00:03:49.900> sagen<00:03:50.300> können. + +00:03:50.690 --> 00:03:50.700 align:start position:0% +dazu sagen können. + + +00:03:50.700 --> 00:03:53.690 align:start position:0% +dazu sagen können. +[applaus] + +00:03:53.690 --> 00:03:53.700 align:start position:0% +[applaus] + + +00:03:53.700 --> 00:03:56.490 align:start position:0% +[applaus] +Ich<00:03:54.100> weiß,<00:03:54.500> dass<00:03:54.900> das<00:03:55.300> alles<00:03:55.700> nicht<00:03:56.100> spektakulär + +00:03:56.490 --> 00:03:56.500 align:start position:0% +Ich weiß, dass das alles nicht spektakulär + + +00:03:56.500 --> 00:03:58.890 align:start position:0% +Ich weiß, dass das alles nicht spektakulär +klingt.<00:03:56.900> Eine<00:03:57.300> Schule,<00:03:57.700> eine<00:03:58.100> Straße,<00:03:58.500> ein + +00:03:58.890 --> 00:03:58.900 align:start position:0% +klingt. Eine Schule, eine Straße, ein + + +00:03:58.900 --> 00:04:00.890 align:start position:0% +klingt. Eine Schule, eine Straße, ein +Laden.<00:03:59.300> Aber<00:03:59.700> genau<00:04:00.100> darum<00:04:00.500> geht + +00:04:00.890 --> 00:04:00.900 align:start position:0% +Laden. Aber genau darum geht + + +00:04:00.900 --> 00:04:03.690 align:start position:0% +Laden. Aber genau darum geht +es<00:04:01.300> in<00:04:01.700> einer<00:04:02.100> Gemeinde<00:04:02.500> wie<00:04:02.900> unserer.<00:04:03.300> Es + +00:04:03.690 --> 00:04:03.700 align:start position:0% +es in einer Gemeinde wie unserer. Es + + +00:04:03.700 --> 00:04:06.090 align:start position:0% +es in einer Gemeinde wie unserer. Es +geht<00:04:04.100> nicht<00:04:04.500> um<00:04:04.900> große<00:04:05.300> Worte.<00:04:05.700> Es + +00:04:06.090 --> 00:04:06.100 align:start position:0% +geht nicht um große Worte. Es + + +00:04:06.100 --> 00:04:09.290 align:start position:0% +geht nicht um große Worte. Es +geht<00:04:06.500> darum,<00:04:06.900> dass<00:04:07.300> das<00:04:07.700> Leben<00:04:08.100> hier<00:04:08.500> gut<00:04:08.900> funktioniert. + +00:04:09.290 --> 00:04:09.300 align:start position:0% +geht darum, dass das Leben hier gut funktioniert. + + +00:04:09.300 --> 00:04:11.690 align:start position:0% +geht darum, dass das Leben hier gut funktioniert. +Für<00:04:09.700> die<00:04:10.100> Kinder,<00:04:10.500> für<00:04:10.900> die<00:04:11.300> Familien, + +00:04:11.690 --> 00:04:11.700 align:start position:0% +Für die Kinder, für die Familien, + + +00:04:11.700 --> 00:04:12.890 align:start position:0% +Für die Kinder, für die Familien, +für<00:04:12.100> die<00:04:12.500> Älteren. + +00:04:12.890 --> 00:04:12.900 align:start position:0% +für die Älteren. + + +00:04:12.900 --> 00:04:15.690 align:start position:0% +für die Älteren. +Lassen<00:04:13.300> Sie<00:04:13.700> mich<00:04:14.100> noch<00:04:14.500> etwas<00:04:14.900> zum<00:04:15.300> Ehrenamt + +00:04:15.690 --> 00:04:15.700 align:start position:0% +Lassen Sie mich noch etwas zum Ehrenamt + + +00:04:15.700 --> 00:04:18.090 align:start position:0% +Lassen Sie mich noch etwas zum Ehrenamt +sagen.<00:04:16.100> Ohne<00:04:16.500> die<00:04:16.900> Vereine<00:04:17.300> wäre<00:04:17.700> Auen + +00:04:18.090 --> 00:04:18.100 align:start position:0% +sagen. Ohne die Vereine wäre Auen + + +00:04:18.100 --> 00:04:20.090 align:start position:0% +sagen. Ohne die Vereine wäre Auen +Tal<00:04:18.500> ein<00:04:18.900> anderer<00:04:19.300> Ort.<00:04:19.700> Wir + +00:04:20.090 --> 00:04:20.100 align:start position:0% +Tal ein anderer Ort. Wir + + +00:04:20.100 --> 00:04:22.890 align:start position:0% +Tal ein anderer Ort. Wir +haben<00:04:20.500> einen<00:04:20.900> Sportverein,<00:04:21.300> einen<00:04:21.700> Gesangverein,<00:04:22.100> eine<00:04:22.500> freiwillige + +00:04:22.890 --> 00:04:22.900 align:start position:0% +haben einen Sportverein, einen Gesangverein, eine freiwillige + + +00:04:22.900 --> 00:04:25.290 align:start position:0% +haben einen Sportverein, einen Gesangverein, eine freiwillige +Feuerwehr,<00:04:23.300> einen<00:04:23.700> Heimatverein<00:04:24.100> und<00:04:24.500> einen<00:04:24.900> Kleintierzuchtverein. + +00:04:25.290 --> 00:04:25.300 align:start position:0% +Feuerwehr, einen Heimatverein und einen Kleintierzuchtverein. + + +00:04:25.300 --> 00:04:28.490 align:start position:0% +Feuerwehr, einen Heimatverein und einen Kleintierzuchtverein. +Wir<00:04:25.700> haben<00:04:26.100> eine<00:04:26.500> Theatergruppe,<00:04:26.900> die<00:04:27.300> jedes<00:04:27.700> Jahr<00:04:28.100> im + +00:04:28.490 --> 00:04:28.500 align:start position:0% +Wir haben eine Theatergruppe, die jedes Jahr im + + +00:04:28.500 --> 00:04:30.890 align:start position:0% +Wir haben eine Theatergruppe, die jedes Jahr im +Winter<00:04:28.900> ein<00:04:29.300> Stück<00:04:29.700> aufführt.<00:04:30.100> Und<00:04:30.500> wir + +00:04:30.890 --> 00:04:30.900 align:start position:0% +Winter ein Stück aufführt. Und wir + + +00:04:30.900 --> 00:04:32.490 align:start position:0% +Winter ein Stück aufführt. Und wir +haben<00:04:31.300> seit<00:04:31.700> drei<00:04:32.100> Jahren + +00:04:32.490 --> 00:04:32.500 align:start position:0% +haben seit drei Jahren + + +00:04:32.500 --> 00:04:35.290 align:start position:0% +haben seit drei Jahren +ein<00:04:32.900> Repaircafé,<00:04:33.300> in<00:04:33.700> dem<00:04:34.100> Menschen<00:04:34.500> ihre<00:04:34.900> kaputten + +00:04:35.290 --> 00:04:35.300 align:start position:0% +ein Repaircafé, in dem Menschen ihre kaputten + + +00:04:35.300 --> 00:04:37.690 align:start position:0% +ein Repaircafé, in dem Menschen ihre kaputten +Toaster<00:04:35.700> und<00:04:36.100> Fahrräder<00:04:36.500> reparieren<00:04:36.900> lassen<00:04:37.300> können. + +00:04:37.690 --> 00:04:37.700 align:start position:0% +Toaster und Fahrräder reparieren lassen können. + + +00:04:37.700 --> 00:04:39.690 align:start position:0% +Toaster und Fahrräder reparieren lassen können. +Das<00:04:38.100> alles<00:04:38.500> funktioniert<00:04:38.900> nur,<00:04:39.300> weil + +00:04:39.690 --> 00:04:39.700 align:start position:0% +Das alles funktioniert nur, weil + + +00:04:39.700 --> 00:04:42.490 align:start position:0% +Das alles funktioniert nur, weil +Menschen<00:04:40.100> ihre<00:04:40.500> freie<00:04:40.900> Zeit<00:04:41.300> hergeben.<00:04:41.700> Sie<00:04:42.100> tun + +00:04:42.490 --> 00:04:42.500 align:start position:0% +Menschen ihre freie Zeit hergeben. Sie tun + + +00:04:42.500 --> 00:04:44.890 align:start position:0% +Menschen ihre freie Zeit hergeben. Sie tun +das<00:04:42.900> ohne<00:04:43.300> Bezahlung<00:04:43.700> und<00:04:44.100> oft<00:04:44.500> ohne + +00:04:44.890 --> 00:04:44.900 align:start position:0% +das ohne Bezahlung und oft ohne + + +00:04:44.900 --> 00:04:48.090 align:start position:0% +das ohne Bezahlung und oft ohne +Dank.<00:04:45.300> Deshalb<00:04:45.700> möchte<00:04:46.100> ich<00:04:46.500> heute<00:04:46.900> ausdrücklich<00:04:47.300> Danke<00:04:47.700> sagen. + +00:04:48.090 --> 00:04:48.100 align:start position:0% +Dank. Deshalb möchte ich heute ausdrücklich Danke sagen. + + +00:04:48.100 --> 00:04:50.490 align:start position:0% +Dank. Deshalb möchte ich heute ausdrücklich Danke sagen. +Danke<00:04:48.500> an<00:04:48.900> alle,<00:04:49.300> die<00:04:49.700> sich<00:04:50.100> engagieren. + +00:04:50.490 --> 00:04:50.500 align:start position:0% +Danke an alle, die sich engagieren. + + +00:04:50.500 --> 00:04:52.090 align:start position:0% +Danke an alle, die sich engagieren. +Sie<00:04:50.900> sind<00:04:51.300> das<00:04:51.700> Herz + +00:04:52.090 --> 00:04:52.100 align:start position:0% +Sie sind das Herz + + +00:04:52.100 --> 00:04:52.890 align:start position:0% +Sie sind das Herz +dieser<00:04:52.500> Gemeinde. + +00:04:52.890 --> 00:04:52.900 align:start position:0% +dieser Gemeinde. + + +00:04:52.900 --> 00:04:55.890 align:start position:0% +dieser Gemeinde. +[applaus] + +00:04:55.890 --> 00:04:55.900 align:start position:0% +[applaus] + + +00:04:55.900 --> 00:04:58.290 align:start position:0% +[applaus] +Ein<00:04:56.300> besonderer<00:04:56.700> Dank<00:04:57.100> geht<00:04:57.500> an<00:04:57.900> die + +00:04:58.290 --> 00:04:58.300 align:start position:0% +Ein besonderer Dank geht an die + + +00:04:58.300 --> 00:05:00.290 align:start position:0% +Ein besonderer Dank geht an die +Freiwillige<00:04:58.700> Feuerwehr.<00:04:59.100> Sie<00:04:59.500> feiert<00:04:59.900> in + +00:05:00.290 --> 00:05:00.300 align:start position:0% +Freiwillige Feuerwehr. Sie feiert in + + +00:05:00.300 --> 00:05:03.090 align:start position:0% +Freiwillige Feuerwehr. Sie feiert in +diesem<00:05:00.700> Jahr<00:05:01.100> ebenfalls<00:05:01.500> ein<00:05:01.900> Jubiläum,<00:05:02.300> nämlich<00:05:02.700> ihr + +00:05:03.090 --> 00:05:03.100 align:start position:0% +diesem Jahr ebenfalls ein Jubiläum, nämlich ihr + + +00:05:03.100 --> 00:05:05.490 align:start position:0% +diesem Jahr ebenfalls ein Jubiläum, nämlich ihr +hundertfünfzigjähriges.<00:05:03.500> Der<00:05:03.900> Wehrführer<00:05:04.300> Bernd<00:05:04.700> Ols<00:05:05.100> Hausen + +00:05:05.490 --> 00:05:05.500 align:start position:0% +hundertfünfzigjähriges. Der Wehrführer Bernd Ols Hausen + + +00:05:05.500 --> 00:05:08.690 align:start position:0% +hundertfünfzigjähriges. Der Wehrführer Bernd Ols Hausen +hat<00:05:05.900> mir<00:05:06.300> erzählt,<00:05:06.700> dass<00:05:07.100> die<00:05:07.500> erste<00:05:07.900> Spritze<00:05:08.300> noch + +00:05:08.690 --> 00:05:08.700 align:start position:0% +hat mir erzählt, dass die erste Spritze noch + + +00:05:08.700 --> 00:05:11.090 align:start position:0% +hat mir erzählt, dass die erste Spritze noch +von<00:05:09.100> Pferden<00:05:09.500> gezogen<00:05:09.900> wurde.<00:05:10.300> Heute<00:05:10.700> hat + +00:05:11.090 --> 00:05:11.100 align:start position:0% +von Pferden gezogen wurde. Heute hat + + +00:05:11.100 --> 00:05:12.690 align:start position:0% +von Pferden gezogen wurde. Heute hat +die<00:05:11.500> Wehr<00:05:11.900> zwei<00:05:12.300> moderne + +00:05:12.690 --> 00:05:12.700 align:start position:0% +die Wehr zwei moderne + + +00:05:12.700 --> 00:05:15.490 align:start position:0% +die Wehr zwei moderne +Fahrzeuge.<00:05:13.100> Aber<00:05:13.500> eines<00:05:13.900> ist<00:05:14.300> gleich<00:05:14.700> geblieben.<00:05:15.100> Wenn + +00:05:15.490 --> 00:05:15.500 align:start position:0% +Fahrzeuge. Aber eines ist gleich geblieben. Wenn + + +00:05:15.500 --> 00:05:17.890 align:start position:0% +Fahrzeuge. Aber eines ist gleich geblieben. Wenn +die<00:05:15.900> Sirene<00:05:16.300> geht,<00:05:16.700> lassen<00:05:17.100> die<00:05:17.500> Frauen + +00:05:17.890 --> 00:05:17.900 align:start position:0% +die Sirene geht, lassen die Frauen + + +00:05:17.900 --> 00:05:19.890 align:start position:0% +die Sirene geht, lassen die Frauen +und<00:05:18.300> Männer<00:05:18.700> alles<00:05:19.100> stehen<00:05:19.500> und + +00:05:19.890 --> 00:05:19.900 align:start position:0% +und Männer alles stehen und + + +00:05:19.900 --> 00:05:22.690 align:start position:0% +und Männer alles stehen und +liegen<00:05:20.300> und<00:05:20.700> rücken<00:05:21.100> aus.<00:05:21.500> Das<00:05:21.900> verdient<00:05:22.300> unseren + +00:05:22.690 --> 00:05:22.700 align:start position:0% +liegen und rücken aus. Das verdient unseren + + +00:05:22.700 --> 00:05:23.090 align:start position:0% +liegen und rücken aus. Das verdient unseren +Respekt. + +00:05:23.090 --> 00:05:23.100 align:start position:0% +Respekt. + + +00:05:23.100 --> 00:05:26.290 align:start position:0% +Respekt. +Liebe<00:05:23.500> Gäste,<00:05:23.900> wir<00:05:24.300> haben<00:05:24.700> für<00:05:25.100> das<00:05:25.500> Jubiläumsjahr<00:05:25.900> ein + +00:05:26.290 --> 00:05:26.300 align:start position:0% +Liebe Gäste, wir haben für das Jubiläumsjahr ein + + +00:05:26.300 --> 00:05:28.690 align:start position:0% +Liebe Gäste, wir haben für das Jubiläumsjahr ein +Programm<00:05:26.700> vorbereitet,<00:05:27.100> das<00:05:27.500> sich<00:05:27.900> über<00:05:28.300> den + +00:05:28.690 --> 00:05:28.700 align:start position:0% +Programm vorbereitet, das sich über den + + +00:05:28.700 --> 00:05:30.290 align:start position:0% +Programm vorbereitet, das sich über den +ganzen<00:05:29.100> Sommer<00:05:29.500> zieht.<00:05:29.900> Ich + +00:05:30.290 --> 00:05:30.300 align:start position:0% +ganzen Sommer zieht. Ich + + +00:05:30.300 --> 00:05:33.090 align:start position:0% +ganzen Sommer zieht. Ich +will<00:05:30.700> Ihnen<00:05:31.100> nur<00:05:31.500> einige<00:05:31.900> Höhepunkte<00:05:32.300> nennen.<00:05:32.700> Im + +00:05:33.090 --> 00:05:33.100 align:start position:0% +will Ihnen nur einige Höhepunkte nennen. Im + + +00:05:33.100 --> 00:05:35.490 align:start position:0% +will Ihnen nur einige Höhepunkte nennen. Im +Juni<00:05:33.500> gibt<00:05:33.900> es<00:05:34.300> ein<00:05:34.700> Mühlenfest<00:05:35.100> mit + +00:05:35.490 --> 00:05:35.500 align:start position:0% +Juni gibt es ein Mühlenfest mit + + +00:05:35.500 --> 00:05:37.490 align:start position:0% +Juni gibt es ein Mühlenfest mit +Führungen<00:05:35.900> und<00:05:36.300> einem<00:05:36.700> Markt.<00:05:37.100> Im + +00:05:37.490 --> 00:05:37.500 align:start position:0% +Führungen und einem Markt. Im + + +00:05:37.500 --> 00:05:40.290 align:start position:0% +Führungen und einem Markt. Im +Juli<00:05:37.900> zeigt<00:05:38.300> die<00:05:38.700> Theatergruppe<00:05:39.100> ein<00:05:39.500> Stück<00:05:39.900> über + +00:05:40.290 --> 00:05:40.300 align:start position:0% +Juli zeigt die Theatergruppe ein Stück über + + +00:05:40.300 --> 00:05:42.690 align:start position:0% +Juli zeigt die Theatergruppe ein Stück über +die<00:05:40.700> Geschichte<00:05:41.100> des<00:05:41.500> Ortes.<00:05:41.900> Im<00:05:42.300> August + +00:05:42.690 --> 00:05:42.700 align:start position:0% +die Geschichte des Ortes. Im August + + +00:05:42.700 --> 00:05:45.890 align:start position:0% +die Geschichte des Ortes. Im August +feiern<00:05:43.100> wir<00:05:43.500> ein<00:05:43.900> Dorffest<00:05:44.300> auf<00:05:44.700> dem<00:05:45.100> Anger<00:05:45.500> mit + +00:05:45.890 --> 00:05:45.900 align:start position:0% +feiern wir ein Dorffest auf dem Anger mit + + +00:05:45.900 --> 00:05:48.290 align:start position:0% +feiern wir ein Dorffest auf dem Anger mit +Musik<00:05:46.300> und<00:05:46.700> Tanz.<00:05:47.100> Und<00:05:47.500> im<00:05:47.900> September + +00:05:48.290 --> 00:05:48.300 align:start position:0% +Musik und Tanz. Und im September + + +00:05:48.300 --> 00:05:49.890 align:start position:0% +Musik und Tanz. Und im September +gibt<00:05:48.700> es<00:05:49.100> eine<00:05:49.500> Ausstellung + +00:05:49.890 --> 00:05:49.900 align:start position:0% +gibt es eine Ausstellung + + +00:05:49.900 --> 00:05:52.690 align:start position:0% +gibt es eine Ausstellung +im<00:05:50.300> Rathaus<00:05:50.700> mit<00:05:51.100> alten<00:05:51.500> Fotos<00:05:51.900> aus<00:05:52.300> Auen + +00:05:52.690 --> 00:05:52.700 align:start position:0% +im Rathaus mit alten Fotos aus Auen + + +00:05:52.700 --> 00:05:53.090 align:start position:0% +im Rathaus mit alten Fotos aus Auen +Tal. + +00:05:53.090 --> 00:05:53.100 align:start position:0% +Tal. + + +00:05:53.100 --> 00:05:55.090 align:start position:0% +Tal. +Für<00:05:53.500> diese<00:05:53.900> Ausstellung<00:05:54.300> suchen<00:05:54.700> wir + +00:05:55.090 --> 00:05:55.100 align:start position:0% +Für diese Ausstellung suchen wir + + +00:05:55.100 --> 00:05:57.890 align:start position:0% +Für diese Ausstellung suchen wir +übrigens<00:05:55.500> noch<00:05:55.900> Bilder.<00:05:56.300> Wenn<00:05:56.700> Sie<00:05:57.100> zu<00:05:57.500> Hause + +00:05:57.890 --> 00:05:57.900 align:start position:0% +übrigens noch Bilder. Wenn Sie zu Hause + + +00:05:57.900 --> 00:06:00.290 align:start position:0% +übrigens noch Bilder. Wenn Sie zu Hause +alte<00:05:58.300> Fotos<00:05:58.700> haben,<00:05:59.100> z.<00:05:59.500> B.<00:05:59.900> von + +00:06:00.290 --> 00:06:00.300 align:start position:0% +alte Fotos haben, z. B. von + + +00:06:00.300 --> 00:06:03.490 align:start position:0% +alte Fotos haben, z. B. von +Hochzeiten,<00:06:00.700> von<00:06:01.100> Festen<00:06:01.500> oder<00:06:01.900> einfach<00:06:02.300> vom<00:06:02.700> Alltag,<00:06:03.100> dann + +00:06:03.490 --> 00:06:03.500 align:start position:0% +Hochzeiten, von Festen oder einfach vom Alltag, dann + + +00:06:03.500 --> 00:06:05.890 align:start position:0% +Hochzeiten, von Festen oder einfach vom Alltag, dann +bringen<00:06:03.900> Sie<00:06:04.300> sie<00:06:04.700> bitte<00:06:05.100> ins<00:06:05.500> Rathaus. + +00:06:05.890 --> 00:06:05.900 align:start position:0% +bringen Sie sie bitte ins Rathaus. + + +00:06:05.900 --> 00:06:07.490 align:start position:0% +bringen Sie sie bitte ins Rathaus. +Wir<00:06:06.300> scannen<00:06:06.700> sie<00:06:07.100> und + +00:06:07.490 --> 00:06:07.500 align:start position:0% +Wir scannen sie und + + +00:06:07.500 --> 00:06:10.290 align:start position:0% +Wir scannen sie und +geben<00:06:07.900> sie<00:06:08.300> Ihnen<00:06:08.700> sofort<00:06:09.100> zurück.<00:06:09.500> Frau<00:06:09.900> Haber + +00:06:10.290 --> 00:06:10.300 align:start position:0% +geben sie Ihnen sofort zurück. Frau Haber + + +00:06:10.300 --> 00:06:12.690 align:start position:0% +geben sie Ihnen sofort zurück. Frau Haber +Kamp<00:06:10.700> hat<00:06:11.100> mir<00:06:11.500> versichert,<00:06:11.900> dass<00:06:12.300> solche + +00:06:12.690 --> 00:06:12.700 align:start position:0% +Kamp hat mir versichert, dass solche + + +00:06:12.700 --> 00:06:14.690 align:start position:0% +Kamp hat mir versichert, dass solche +Bilder<00:06:13.100> für<00:06:13.500> das<00:06:13.900> Archiv<00:06:14.300> ein + +00:06:14.690 --> 00:06:14.700 align:start position:0% +Bilder für das Archiv ein + + +00:06:14.700 --> 00:06:15.890 align:start position:0% +Bilder für das Archiv ein +großer<00:06:15.100> Schatz<00:06:15.500> sind. + +00:06:15.890 --> 00:06:15.900 align:start position:0% +großer Schatz sind. + + +00:06:15.900 --> 00:06:18.290 align:start position:0% +großer Schatz sind. +Ich<00:06:16.300> möchte<00:06:16.700> auch<00:06:17.100> etwas<00:06:17.500> zu<00:06:17.900> unseren + +00:06:18.290 --> 00:06:18.300 align:start position:0% +Ich möchte auch etwas zu unseren + + +00:06:18.300 --> 00:06:21.490 align:start position:0% +Ich möchte auch etwas zu unseren +Partnern<00:06:18.700> sagen.<00:06:19.100> Seit<00:06:19.500> über<00:06:19.900> dreißig<00:06:20.300> Jahren<00:06:20.700> haben<00:06:21.100> wir + +00:06:21.490 --> 00:06:21.500 align:start position:0% +Partnern sagen. Seit über dreißig Jahren haben wir + + +00:06:21.500 --> 00:06:23.890 align:start position:0% +Partnern sagen. Seit über dreißig Jahren haben wir +eine<00:06:21.900> Partnerschaft<00:06:22.300> mit<00:06:22.700> der<00:06:23.100> Gemeinde<00:06:23.500> Saint + +00:06:23.890 --> 00:06:23.900 align:start position:0% +eine Partnerschaft mit der Gemeinde Saint + + +00:06:23.900 --> 00:06:25.490 align:start position:0% +eine Partnerschaft mit der Gemeinde Saint +Maur<00:06:24.300> in<00:06:24.700> Frankreich.<00:06:25.100> Eine + +00:06:25.490 --> 00:06:25.500 align:start position:0% +Maur in Frankreich. Eine + + +00:06:25.500 --> 00:06:28.290 align:start position:0% +Maur in Frankreich. Eine +Delegation<00:06:25.900> aus<00:06:26.300> Saint<00:06:26.700> Maur<00:06:27.100> ist<00:06:27.500> heute<00:06:27.900> hier. + +00:06:28.290 --> 00:06:28.300 align:start position:0% +Delegation aus Saint Maur ist heute hier. + + +00:06:28.300 --> 00:06:30.690 align:start position:0% +Delegation aus Saint Maur ist heute hier. +Bienvenue,<00:06:28.700> liebe<00:06:29.100> Freunde.<00:06:29.500> Wir<00:06:29.900> freuen<00:06:30.300> uns + +00:06:30.690 --> 00:06:30.700 align:start position:0% +Bienvenue, liebe Freunde. Wir freuen uns + + +00:06:30.700 --> 00:06:32.690 align:start position:0% +Bienvenue, liebe Freunde. Wir freuen uns +sehr,<00:06:31.100> dass<00:06:31.500> Sie<00:06:31.900> die<00:06:32.300> weite + +00:06:32.690 --> 00:06:32.700 align:start position:0% +sehr, dass Sie die weite + + +00:06:32.700 --> 00:06:34.690 align:start position:0% +sehr, dass Sie die weite +Reise<00:06:33.100> auf<00:06:33.500> sich<00:06:33.900> genommen<00:06:34.300> haben. + +00:06:34.690 --> 00:06:34.700 align:start position:0% +Reise auf sich genommen haben. + + +00:06:34.700 --> 00:06:37.690 align:start position:0% +Reise auf sich genommen haben. +[applaus] + +00:06:37.690 --> 00:06:37.700 align:start position:0% +[applaus] + + +00:06:37.700 --> 00:06:40.090 align:start position:0% +[applaus] +Die<00:06:38.100> Partnerschaft<00:06:38.500> hat<00:06:38.900> mit<00:06:39.300> einem<00:06:39.700> Schüleraustausch + +00:06:40.090 --> 00:06:40.100 align:start position:0% +Die Partnerschaft hat mit einem Schüleraustausch + + +00:06:40.100 --> 00:06:43.290 align:start position:0% +Die Partnerschaft hat mit einem Schüleraustausch +angefangen.<00:06:40.500> Inzwischen<00:06:40.900> gibt<00:06:41.300> es<00:06:41.700> Besuche<00:06:42.100> der<00:06:42.500> Vereine,<00:06:42.900> der + +00:06:43.290 --> 00:06:43.300 align:start position:0% +angefangen. Inzwischen gibt es Besuche der Vereine, der + + +00:06:43.300 --> 00:06:45.690 align:start position:0% +angefangen. Inzwischen gibt es Besuche der Vereine, der +Feuerwehren<00:06:43.700> und<00:06:44.100> der<00:06:44.500> Chöre.<00:06:44.900> Es<00:06:45.300> gibt + +00:06:45.690 --> 00:06:45.700 align:start position:0% +Feuerwehren und der Chöre. Es gibt + + +00:06:45.700 --> 00:06:47.290 align:start position:0% +Feuerwehren und der Chöre. Es gibt +sogar<00:06:46.100> zwei<00:06:46.500> Ehen,<00:06:46.900> die + +00:06:47.290 --> 00:06:47.300 align:start position:0% +sogar zwei Ehen, die + + +00:06:47.300 --> 00:06:50.090 align:start position:0% +sogar zwei Ehen, die +aus<00:06:47.700> dieser<00:06:48.100> Partnerschaft<00:06:48.500> entstanden<00:06:48.900> sind.<00:06:49.300> Auch<00:06:49.700> hier + +00:06:50.090 --> 00:06:50.100 align:start position:0% +aus dieser Partnerschaft entstanden sind. Auch hier + + +00:06:50.100 --> 00:06:51.690 align:start position:0% +aus dieser Partnerschaft entstanden sind. Auch hier +nenne<00:06:50.500> ich<00:06:50.900> keine<00:06:51.300> Namen. + +00:06:51.690 --> 00:06:51.700 align:start position:0% +nenne ich keine Namen. + + +00:06:51.700 --> 00:06:53.690 align:start position:0% +nenne ich keine Namen. +Meine<00:06:52.100> Damen<00:06:52.500> und<00:06:52.900> Herren,<00:06:53.300> ich + +00:06:53.690 --> 00:06:53.700 align:start position:0% +Meine Damen und Herren, ich + + +00:06:53.700 --> 00:06:56.490 align:start position:0% +Meine Damen und Herren, ich +habe<00:06:54.100> vorhin<00:06:54.500> gesagt,<00:06:54.900> dass<00:06:55.300> wir<00:06:55.700> wieder<00:06:56.100> aufbauen, + +00:06:56.490 --> 00:06:56.500 align:start position:0% +habe vorhin gesagt, dass wir wieder aufbauen, + + +00:06:56.500 --> 00:06:58.890 align:start position:0% +habe vorhin gesagt, dass wir wieder aufbauen, +wenn<00:06:56.900> etwas<00:06:57.300> kaputtgeht.<00:06:57.700> Das<00:06:58.100> gilt<00:06:58.500> nicht + +00:06:58.890 --> 00:06:58.900 align:start position:0% +wenn etwas kaputtgeht. Das gilt nicht + + +00:06:58.900 --> 00:07:02.090 align:start position:0% +wenn etwas kaputtgeht. Das gilt nicht +nur<00:06:59.300> für<00:06:59.700> Gebäude.<00:07:00.100> Es<00:07:00.500> gilt<00:07:00.900> auch<00:07:01.300> für<00:07:01.700> das + +00:07:02.090 --> 00:07:02.100 align:start position:0% +nur für Gebäude. Es gilt auch für das + + +00:07:02.100 --> 00:07:04.490 align:start position:0% +nur für Gebäude. Es gilt auch für das +Miteinander.<00:07:02.500> Auch<00:07:02.900> bei<00:07:03.300> uns<00:07:03.700> gibt<00:07:04.100> es + +00:07:04.490 --> 00:07:04.500 align:start position:0% +Miteinander. Auch bei uns gibt es + + +00:07:04.500 --> 00:07:06.090 align:start position:0% +Miteinander. Auch bei uns gibt es +Streit.<00:07:04.900> Es<00:07:05.300> gibt<00:07:05.700> Streit + +00:07:06.090 --> 00:07:06.100 align:start position:0% +Streit. Es gibt Streit + + +00:07:06.100 --> 00:07:08.890 align:start position:0% +Streit. Es gibt Streit +über<00:07:06.500> den<00:07:06.900> Windpark,<00:07:07.300> über<00:07:07.700> die<00:07:08.100> Parkplätze<00:07:08.500> am + +00:07:08.890 --> 00:07:08.900 align:start position:0% +über den Windpark, über die Parkplätze am + + +00:07:08.900 --> 00:07:11.290 align:start position:0% +über den Windpark, über die Parkplätze am +Friedhof<00:07:09.300> und<00:07:09.700> über<00:07:10.100> die<00:07:10.500> Frage,<00:07:10.900> ob + +00:07:11.290 --> 00:07:11.300 align:start position:0% +Friedhof und über die Frage, ob + + +00:07:11.300 --> 00:07:13.290 align:start position:0% +Friedhof und über die Frage, ob +der<00:07:11.700> Weihnachtsbaum<00:07:12.100> auf<00:07:12.500> dem<00:07:12.900> Marktplatz + +00:07:13.290 --> 00:07:13.300 align:start position:0% +der Weihnachtsbaum auf dem Marktplatz + + +00:07:13.300 --> 00:07:16.090 align:start position:0% +der Weihnachtsbaum auf dem Marktplatz +echt<00:07:13.700> sein<00:07:14.100> muss<00:07:14.500> oder<00:07:14.900> aus<00:07:15.300> Plastik<00:07:15.700> sein + +00:07:16.090 --> 00:07:16.100 align:start position:0% +echt sein muss oder aus Plastik sein + + +00:07:16.100 --> 00:07:16.490 align:start position:0% +echt sein muss oder aus Plastik sein +darf. + +00:07:16.490 --> 00:07:16.500 align:start position:0% +darf. + + +00:07:16.500 --> 00:07:19.490 align:start position:0% +darf. +[lachen] + +00:07:19.490 --> 00:07:19.500 align:start position:0% +[lachen] + + +00:07:19.500 --> 00:07:22.690 align:start position:0% +[lachen] +Streit<00:07:19.900> gehört<00:07:20.300> dazu.<00:07:20.700> Aber<00:07:21.100> wir<00:07:21.500> sollten<00:07:21.900> uns<00:07:22.300> dabei + +00:07:22.690 --> 00:07:22.700 align:start position:0% +Streit gehört dazu. Aber wir sollten uns dabei + + +00:07:22.700 --> 00:07:25.090 align:start position:0% +Streit gehört dazu. Aber wir sollten uns dabei +nicht<00:07:23.100> aus<00:07:23.500> den<00:07:23.900> Augen<00:07:24.300> verlieren.<00:07:24.700> Wir + +00:07:25.090 --> 00:07:25.100 align:start position:0% +nicht aus den Augen verlieren. Wir + + +00:07:25.100 --> 00:07:26.690 align:start position:0% +nicht aus den Augen verlieren. Wir +sollten<00:07:25.500> miteinander<00:07:25.900> reden<00:07:26.300> und + +00:07:26.690 --> 00:07:26.700 align:start position:0% +sollten miteinander reden und + + +00:07:26.700 --> 00:07:29.490 align:start position:0% +sollten miteinander reden und +nicht<00:07:27.100> übereinander.<00:07:27.500> Wir<00:07:27.900> sollten<00:07:28.300> zuhören,<00:07:28.700> auch<00:07:29.100> wenn + +00:07:29.490 --> 00:07:29.500 align:start position:0% +nicht übereinander. Wir sollten zuhören, auch wenn + + +00:07:29.500 --> 00:07:31.890 align:start position:0% +nicht übereinander. Wir sollten zuhören, auch wenn +es<00:07:29.900> schwerfällt.<00:07:30.300> Das<00:07:30.700> ist<00:07:31.100> nicht<00:07:31.500> immer + +00:07:31.890 --> 00:07:31.900 align:start position:0% +es schwerfällt. Das ist nicht immer + + +00:07:31.900 --> 00:07:33.890 align:start position:0% +es schwerfällt. Das ist nicht immer +einfach.<00:07:32.300> Ich<00:07:32.700> schaffe<00:07:33.100> das<00:07:33.500> auch + +00:07:33.890 --> 00:07:33.900 align:start position:0% +einfach. Ich schaffe das auch + + +00:07:33.900 --> 00:07:36.290 align:start position:0% +einfach. Ich schaffe das auch +nicht<00:07:34.300> immer.<00:07:34.700> Aber<00:07:35.100> ich<00:07:35.500> bemühe<00:07:35.900> mich. + +00:07:36.290 --> 00:07:36.300 align:start position:0% +nicht immer. Aber ich bemühe mich. + + +00:07:36.300 --> 00:07:38.690 align:start position:0% +nicht immer. Aber ich bemühe mich. +Lassen<00:07:36.700> Sie<00:07:37.100> mich<00:07:37.500> zum<00:07:37.900> Schluss<00:07:38.300> noch + +00:07:38.690 --> 00:07:38.700 align:start position:0% +Lassen Sie mich zum Schluss noch + + +00:07:38.700 --> 00:07:41.890 align:start position:0% +Lassen Sie mich zum Schluss noch +eine<00:07:39.100> kleine<00:07:39.500> Geschichte<00:07:39.900> erzählen.<00:07:40.300> Als<00:07:40.700> ich<00:07:41.100> vor<00:07:41.500> sechs + +00:07:41.890 --> 00:07:41.900 align:start position:0% +eine kleine Geschichte erzählen. Als ich vor sechs + + +00:07:41.900 --> 00:07:44.290 align:start position:0% +eine kleine Geschichte erzählen. Als ich vor sechs +Jahren<00:07:42.300> zur<00:07:42.700> Bürgermeisterin<00:07:43.100> gewählt<00:07:43.500> wurde,<00:07:43.900> hat + +00:07:44.290 --> 00:07:44.300 align:start position:0% +Jahren zur Bürgermeisterin gewählt wurde, hat + + +00:07:44.300 --> 00:07:45.890 align:start position:0% +Jahren zur Bürgermeisterin gewählt wurde, hat +mir<00:07:44.700> mein<00:07:45.100> Vorgänger<00:07:45.500> einen + +00:07:45.890 --> 00:07:45.900 align:start position:0% +mir mein Vorgänger einen + + +00:07:45.900 --> 00:07:48.690 align:start position:0% +mir mein Vorgänger einen +Schlüssel<00:07:46.300> gegeben.<00:07:46.700> Es<00:07:47.100> war<00:07:47.500> kein<00:07:47.900> Schlüssel<00:07:48.300> für + +00:07:48.690 --> 00:07:48.700 align:start position:0% +Schlüssel gegeben. Es war kein Schlüssel für + + +00:07:48.700 --> 00:07:51.090 align:start position:0% +Schlüssel gegeben. Es war kein Schlüssel für +das<00:07:49.100> Rathaus.<00:07:49.500> Es<00:07:49.900> war<00:07:50.300> der<00:07:50.700> Schlüssel + +00:07:51.090 --> 00:07:51.100 align:start position:0% +das Rathaus. Es war der Schlüssel + + +00:07:51.100 --> 00:07:53.090 align:start position:0% +das Rathaus. Es war der Schlüssel +für<00:07:51.500> den<00:07:51.900> Kirchturm.<00:07:52.300> Er<00:07:52.700> hat + +00:07:53.090 --> 00:07:53.100 align:start position:0% +für den Kirchturm. Er hat + + +00:07:53.100 --> 00:07:55.890 align:start position:0% +für den Kirchturm. Er hat +gesagt,<00:07:53.500> wenn<00:07:53.900> du<00:07:54.300> einmal<00:07:54.700> nicht<00:07:55.100> weiterweißt,<00:07:55.500> dann + +00:07:55.890 --> 00:07:55.900 align:start position:0% +gesagt, wenn du einmal nicht weiterweißt, dann + + +00:07:55.900 --> 00:07:58.290 align:start position:0% +gesagt, wenn du einmal nicht weiterweißt, dann +steig<00:07:56.300> da<00:07:56.700> hoch<00:07:57.100> und<00:07:57.500> schau<00:07:57.900> dir + +00:07:58.290 --> 00:07:58.300 align:start position:0% +steig da hoch und schau dir + + +00:07:58.300 --> 00:08:00.290 align:start position:0% +steig da hoch und schau dir +den<00:07:58.700> Ort<00:07:59.100> von<00:07:59.500> oben<00:07:59.900> an. + +00:08:00.290 --> 00:08:00.300 align:start position:0% +den Ort von oben an. + + +00:08:00.300 --> 00:08:02.690 align:start position:0% +den Ort von oben an. +Ich<00:08:00.700> habe<00:08:01.100> das<00:08:01.500> ein<00:08:01.900> paar<00:08:02.300> Mal + +00:08:02.690 --> 00:08:02.700 align:start position:0% +Ich habe das ein paar Mal + + +00:08:02.700 --> 00:08:04.290 align:start position:0% +Ich habe das ein paar Mal +gemacht.<00:08:03.100> Von<00:08:03.500> oben<00:08:03.900> sieht + +00:08:04.290 --> 00:08:04.300 align:start position:0% +gemacht. Von oben sieht + + +00:08:04.300 --> 00:08:07.090 align:start position:0% +gemacht. Von oben sieht +man<00:08:04.700> die<00:08:05.100> Dächer,<00:08:05.500> die<00:08:05.900> Gärten,<00:08:06.300> den<00:08:06.700> Bach + +00:08:07.090 --> 00:08:07.100 align:start position:0% +man die Dächer, die Gärten, den Bach + + +00:08:07.100 --> 00:08:09.490 align:start position:0% +man die Dächer, die Gärten, den Bach +und<00:08:07.500> die<00:08:07.900> Mühle.<00:08:08.300> Man<00:08:08.700> sieht<00:08:09.100> die + +00:08:09.490 --> 00:08:09.500 align:start position:0% +und die Mühle. Man sieht die + + +00:08:09.500 --> 00:08:11.490 align:start position:0% +und die Mühle. Man sieht die +Felder<00:08:09.900> und<00:08:10.300> den<00:08:10.700> Wald.<00:08:11.100> Man + +00:08:11.490 --> 00:08:11.500 align:start position:0% +Felder und den Wald. Man + + +00:08:11.500 --> 00:08:14.290 align:start position:0% +Felder und den Wald. Man +sieht,<00:08:11.900> wie<00:08:12.300> klein<00:08:12.700> der<00:08:13.100> Ort<00:08:13.500> ist<00:08:13.900> und + +00:08:14.290 --> 00:08:14.300 align:start position:0% +sieht, wie klein der Ort ist und + + +00:08:14.300 --> 00:08:16.690 align:start position:0% +sieht, wie klein der Ort ist und +wie<00:08:14.700> viel<00:08:15.100> trotzdem<00:08:15.500> darin<00:08:15.900> steckt.<00:08:16.300> Und + +00:08:16.690 --> 00:08:16.700 align:start position:0% +wie viel trotzdem darin steckt. Und + + +00:08:16.700 --> 00:08:19.890 align:start position:0% +wie viel trotzdem darin steckt. Und +man<00:08:17.100> merkt,<00:08:17.500> dass<00:08:17.900> die<00:08:18.300> meisten<00:08:18.700> Probleme<00:08:19.100> von<00:08:19.500> dort + +00:08:19.890 --> 00:08:19.900 align:start position:0% +man merkt, dass die meisten Probleme von dort + + +00:08:19.900 --> 00:08:21.890 align:start position:0% +man merkt, dass die meisten Probleme von dort +oben<00:08:20.300> ein<00:08:20.700> bisschen<00:08:21.100> kleiner<00:08:21.500> aussehen. + +00:08:21.890 --> 00:08:21.900 align:start position:0% +oben ein bisschen kleiner aussehen. + + +00:08:21.900 --> 00:08:23.490 align:start position:0% +oben ein bisschen kleiner aussehen. +Ich<00:08:22.300> möchte,<00:08:22.700> dass<00:08:23.100> dieser + +00:08:23.490 --> 00:08:23.500 align:start position:0% +Ich möchte, dass dieser + + +00:08:23.500 --> 00:08:26.290 align:start position:0% +Ich möchte, dass dieser +Ort<00:08:23.900> auch<00:08:24.300> in<00:08:24.700> fünfzig<00:08:25.100> Jahren<00:08:25.500> noch<00:08:25.900> ein + +00:08:26.290 --> 00:08:26.300 align:start position:0% +Ort auch in fünfzig Jahren noch ein + + +00:08:26.300 --> 00:08:28.690 align:start position:0% +Ort auch in fünfzig Jahren noch ein +Ort<00:08:26.700> ist,<00:08:27.100> an<00:08:27.500> dem<00:08:27.900> man<00:08:28.300> gern + +00:08:28.690 --> 00:08:28.700 align:start position:0% +Ort ist, an dem man gern + + +00:08:28.700 --> 00:08:30.690 align:start position:0% +Ort ist, an dem man gern +lebt.<00:08:29.100> Ein<00:08:29.500> Ort,<00:08:29.900> an<00:08:30.300> dem + +00:08:30.690 --> 00:08:30.700 align:start position:0% +lebt. Ein Ort, an dem + + +00:08:30.700 --> 00:08:33.490 align:start position:0% +lebt. Ein Ort, an dem +Kinder<00:08:31.100> zur<00:08:31.500> Schule<00:08:31.900> laufen<00:08:32.300> können.<00:08:32.700> Ein<00:08:33.100> Ort, + +00:08:33.490 --> 00:08:33.500 align:start position:0% +Kinder zur Schule laufen können. Ein Ort, + + +00:08:33.500 --> 00:08:35.890 align:start position:0% +Kinder zur Schule laufen können. Ein Ort, +an<00:08:33.900> dem<00:08:34.300> ältere<00:08:34.700> Menschen<00:08:35.100> nicht<00:08:35.500> allein + +00:08:35.890 --> 00:08:35.900 align:start position:0% +an dem ältere Menschen nicht allein + + +00:08:35.900 --> 00:08:39.090 align:start position:0% +an dem ältere Menschen nicht allein +sind.<00:08:36.300> Ein<00:08:36.700> Ort,<00:08:37.100> an<00:08:37.500> dem<00:08:37.900> man<00:08:38.300> sich<00:08:38.700> kennt + +00:08:39.090 --> 00:08:39.100 align:start position:0% +sind. Ein Ort, an dem man sich kennt + + +00:08:39.100 --> 00:08:41.490 align:start position:0% +sind. Ein Ort, an dem man sich kennt +und<00:08:39.500> sich<00:08:39.900> hilft.<00:08:40.300> Daran<00:08:40.700> arbeiten<00:08:41.100> wir. + +00:08:41.490 --> 00:08:41.500 align:start position:0% +und sich hilft. Daran arbeiten wir. + + +00:08:41.500 --> 00:08:43.090 align:start position:0% +und sich hilft. Daran arbeiten wir. +Und<00:08:41.900> dafür<00:08:42.300> brauchen<00:08:42.700> wir + +00:08:43.090 --> 00:08:43.100 align:start position:0% +Und dafür brauchen wir + + +00:08:43.100 --> 00:08:43.890 align:start position:0% +Und dafür brauchen wir +Sie<00:08:43.500> alle. + +00:08:43.890 --> 00:08:43.900 align:start position:0% +Sie alle. + + +00:08:43.900 --> 00:08:46.290 align:start position:0% +Sie alle. +Bevor<00:08:44.300> ich<00:08:44.700> jetzt<00:08:45.100> das<00:08:45.500> Wort<00:08:45.900> an + +00:08:46.290 --> 00:08:46.300 align:start position:0% +Bevor ich jetzt das Wort an + + +00:08:46.300 --> 00:08:48.290 align:start position:0% +Bevor ich jetzt das Wort an +Frau<00:08:46.700> Dr.<00:08:47.100> Haber<00:08:47.500> Kamp<00:08:47.900> übergebe, + +00:08:48.290 --> 00:08:48.300 align:start position:0% +Frau Dr. Haber Kamp übergebe, + + +00:08:48.300 --> 00:08:51.090 align:start position:0% +Frau Dr. Haber Kamp übergebe, +möchte<00:08:48.700> ich<00:08:49.100> noch<00:08:49.500> einigen<00:08:49.900> Menschen<00:08:50.300> danken.<00:08:50.700> Ich + +00:08:51.090 --> 00:08:51.100 align:start position:0% +möchte ich noch einigen Menschen danken. Ich + + +00:08:51.100 --> 00:08:53.490 align:start position:0% +möchte ich noch einigen Menschen danken. Ich +danke<00:08:51.500> dem<00:08:51.900> Festausschuss,<00:08:52.300> der<00:08:52.700> seit<00:08:53.100> über + +00:08:53.490 --> 00:08:53.500 align:start position:0% +danke dem Festausschuss, der seit über + + +00:08:53.500 --> 00:08:56.690 align:start position:0% +danke dem Festausschuss, der seit über +einem<00:08:53.900> Jahr<00:08:54.300> dieses<00:08:54.700> Jubiläum<00:08:55.100> vorbereitet.<00:08:55.500> Ich<00:08:55.900> danke<00:08:56.300> dem + +00:08:56.690 --> 00:08:56.700 align:start position:0% +einem Jahr dieses Jubiläum vorbereitet. Ich danke dem + + +00:08:56.700 --> 00:08:59.090 align:start position:0% +einem Jahr dieses Jubiläum vorbereitet. Ich danke dem +Bauhof,<00:08:57.100> der<00:08:57.500> den<00:08:57.900> Platz<00:08:58.300> so<00:08:58.700> schön + +00:08:59.090 --> 00:08:59.100 align:start position:0% +Bauhof, der den Platz so schön + + +00:08:59.100 --> 00:09:00.690 align:start position:0% +Bauhof, der den Platz so schön +hergerichtet<00:08:59.500> hat.<00:08:59.900> Ich<00:09:00.300> danke + +00:09:00.690 --> 00:09:00.700 align:start position:0% +hergerichtet hat. Ich danke + + +00:09:00.700 --> 00:09:03.490 align:start position:0% +hergerichtet hat. Ich danke +dem<00:09:01.100> Gesangverein<00:09:01.500> für<00:09:01.900> die<00:09:02.300> Musik.<00:09:02.700> Und<00:09:03.100> ich + +00:09:03.490 --> 00:09:03.500 align:start position:0% +dem Gesangverein für die Musik. Und ich + + +00:09:03.500 --> 00:09:05.890 align:start position:0% +dem Gesangverein für die Musik. Und ich +danke<00:09:03.900> den<00:09:04.300> Landfrauen<00:09:04.700> für<00:09:05.100> den<00:09:05.500> Kuchen, + +00:09:05.890 --> 00:09:05.900 align:start position:0% +danke den Landfrauen für den Kuchen, + + +00:09:05.900 --> 00:09:07.890 align:start position:0% +danke den Landfrauen für den Kuchen, +den<00:09:06.300> Sie<00:09:06.700> nachher<00:09:07.100> alle<00:09:07.500> probieren + +00:09:07.890 --> 00:09:07.900 align:start position:0% +den Sie nachher alle probieren + + +00:09:07.900 --> 00:09:08.290 align:start position:0% +den Sie nachher alle probieren +sollten. + +00:09:08.290 --> 00:09:08.300 align:start position:0% +sollten. + + +00:09:08.300 --> 00:09:11.290 align:start position:0% +sollten. +[lachen] + +00:09:11.290 --> 00:09:11.300 align:start position:0% +[lachen] + + +00:09:11.300 --> 00:09:13.690 align:start position:0% +[lachen] +Ich<00:09:11.700> wünsche<00:09:12.100> uns<00:09:12.500> allen<00:09:12.900> ein<00:09:13.300> schönes + +00:09:13.690 --> 00:09:13.700 align:start position:0% +Ich wünsche uns allen ein schönes + + +00:09:13.700 --> 00:09:16.890 align:start position:0% +Ich wünsche uns allen ein schönes +Fest<00:09:14.100> und<00:09:14.500> ein<00:09:14.900> gutes<00:09:15.300> Jubiläumsjahr.<00:09:15.700> Auf<00:09:16.100> die<00:09:16.500> nächsten + +00:09:16.890 --> 00:09:16.900 align:start position:0% +Fest und ein gutes Jubiläumsjahr. Auf die nächsten + + +00:09:16.900 --> 00:09:18.490 align:start position:0% +Fest und ein gutes Jubiläumsjahr. Auf die nächsten +750<00:09:17.300> Jahre.<00:09:17.700> Vielen<00:09:18.100> Dank. + +00:09:18.490 --> 00:09:18.500 align:start position:0% +750 Jahre. Vielen Dank. + + +00:09:18.500 --> 00:09:21.490 align:start position:0% +750 Jahre. Vielen Dank. +[applaus] + +00:09:21.490 --> 00:09:21.500 align:start position:0% +[applaus] + + +00:09:21.500 --> 00:09:23.090 align:start position:0% +[applaus] +Ja,<00:09:21.900> vielen<00:09:22.300> Dank,<00:09:22.700> Frau + +00:09:23.090 --> 00:09:23.100 align:start position:0% +Ja, vielen Dank, Frau + + +00:09:23.100 --> 00:09:25.890 align:start position:0% +Ja, vielen Dank, Frau +Bürgermeisterin.<00:09:23.500> Liebe<00:09:23.900> Gäste,<00:09:24.300> ich<00:09:24.700> bin<00:09:25.100> Jorinde<00:09:25.500> Haber + +00:09:25.890 --> 00:09:25.900 align:start position:0% +Bürgermeisterin. Liebe Gäste, ich bin Jorinde Haber + + +00:09:25.900 --> 00:09:28.290 align:start position:0% +Bürgermeisterin. Liebe Gäste, ich bin Jorinde Haber +Kamp<00:09:26.300> und<00:09:26.700> leite<00:09:27.100> das<00:09:27.500> Kreisarchiv.<00:09:27.900> Ich + +00:09:28.290 --> 00:09:28.300 align:start position:0% +Kamp und leite das Kreisarchiv. Ich + + +00:09:28.300 --> 00:09:30.290 align:start position:0% +Kamp und leite das Kreisarchiv. Ich +darf<00:09:28.700> Ihnen<00:09:29.100> heute<00:09:29.500> ein<00:09:29.900> wenig + +00:09:30.290 --> 00:09:30.300 align:start position:0% +darf Ihnen heute ein wenig + + +00:09:30.300 --> 00:09:33.090 align:start position:0% +darf Ihnen heute ein wenig +über<00:09:30.700> die<00:09:31.100> Geschichte<00:09:31.500> von<00:09:31.900> Auen<00:09:32.300> Tal<00:09:32.700> erzählen. + +00:09:33.090 --> 00:09:33.100 align:start position:0% +über die Geschichte von Auen Tal erzählen. + + +00:09:33.100 --> 00:09:35.490 align:start position:0% +über die Geschichte von Auen Tal erzählen. +Keine<00:09:33.500> Sorge,<00:09:33.900> ich<00:09:34.300> halte<00:09:34.700> mich<00:09:35.100> kurz. + +00:09:35.490 --> 00:09:35.500 align:start position:0% +Keine Sorge, ich halte mich kurz. + + +00:09:35.500 --> 00:09:38.690 align:start position:0% +Keine Sorge, ich halte mich kurz. +Die<00:09:35.900> Urkunde<00:09:36.300> aus<00:09:36.700> dem<00:09:37.100> Jahr<00:09:37.500> 12<00:09:37.900> 74<00:09:38.300> liegt + +00:09:38.690 --> 00:09:38.700 align:start position:0% +Die Urkunde aus dem Jahr 12 74 liegt + + +00:09:38.700 --> 00:09:41.090 align:start position:0% +Die Urkunde aus dem Jahr 12 74 liegt +bei<00:09:39.100> uns<00:09:39.500> im<00:09:39.900> Archiv.<00:09:40.300> Sie<00:09:40.700> ist + +00:09:41.090 --> 00:09:41.100 align:start position:0% +bei uns im Archiv. Sie ist + + +00:09:41.100 --> 00:09:42.690 align:start position:0% +bei uns im Archiv. Sie ist +auf<00:09:41.500> Pergament<00:09:41.900> geschrieben,<00:09:42.300> in + +00:09:42.690 --> 00:09:42.700 align:start position:0% +auf Pergament geschrieben, in + + +00:09:42.700 --> 00:09:45.490 align:start position:0% +auf Pergament geschrieben, in +lateinischer<00:09:43.100> Sprache,<00:09:43.500> und<00:09:43.900> sie<00:09:44.300> ist<00:09:44.700> erstaunlich<00:09:45.100> gut + +00:09:45.490 --> 00:09:45.500 align:start position:0% +lateinischer Sprache, und sie ist erstaunlich gut + + +00:09:45.500 --> 00:09:47.890 align:start position:0% +lateinischer Sprache, und sie ist erstaunlich gut +erhalten.<00:09:45.900> Es<00:09:46.300> geht<00:09:46.700> darin<00:09:47.100> um<00:09:47.500> einen + +00:09:47.890 --> 00:09:47.900 align:start position:0% +erhalten. Es geht darin um einen + + +00:09:47.900 --> 00:09:49.890 align:start position:0% +erhalten. Es geht darin um einen +Streit<00:09:48.300> über<00:09:48.700> Wasserrechte.<00:09:49.100> Zwei<00:09:49.500> Klöster + +00:09:49.890 --> 00:09:49.900 align:start position:0% +Streit über Wasserrechte. Zwei Klöster + + +00:09:49.900 --> 00:09:52.690 align:start position:0% +Streit über Wasserrechte. Zwei Klöster +stritten<00:09:50.300> sich<00:09:50.700> darüber,<00:09:51.100> wer<00:09:51.500> die<00:09:51.900> Mühle<00:09:52.300> am + +00:09:52.690 --> 00:09:52.700 align:start position:0% +stritten sich darüber, wer die Mühle am + + +00:09:52.700 --> 00:09:55.090 align:start position:0% +stritten sich darüber, wer die Mühle am +Bach<00:09:53.100> nutzen<00:09:53.500> darf.<00:09:53.900> Der<00:09:54.300> Ort<00:09:54.700> selbst + +00:09:55.090 --> 00:09:55.100 align:start position:0% +Bach nutzen darf. Der Ort selbst + + +00:09:55.100 --> 00:09:58.290 align:start position:0% +Bach nutzen darf. Der Ort selbst +wird<00:09:55.500> nur<00:09:55.900> nebenbei<00:09:56.300> erwähnt.<00:09:56.700> Aber<00:09:57.100> er<00:09:57.500> wird<00:09:57.900> erwähnt, + +00:09:58.290 --> 00:09:58.300 align:start position:0% +wird nur nebenbei erwähnt. Aber er wird erwähnt, + + +00:09:58.300 --> 00:10:00.290 align:start position:0% +wird nur nebenbei erwähnt. Aber er wird erwähnt, +und<00:09:58.700> deshalb<00:09:59.100> feiern<00:09:59.500> wir<00:09:59.900> heute. + +00:10:00.290 --> 00:10:00.300 align:start position:0% +und deshalb feiern wir heute. + + +00:10:00.300 --> 00:10:01.890 align:start position:0% +und deshalb feiern wir heute. +Was<00:10:00.700> wissen<00:10:01.100> wir<00:10:01.500> über + +00:10:01.890 --> 00:10:01.900 align:start position:0% +Was wissen wir über + + +00:10:01.900 --> 00:10:04.690 align:start position:0% +Was wissen wir über +die<00:10:02.300> Menschen,<00:10:02.700> die<00:10:03.100> damals<00:10:03.500> hier<00:10:03.900> gelebt<00:10:04.300> haben? + +00:10:04.690 --> 00:10:04.700 align:start position:0% +die Menschen, die damals hier gelebt haben? + + +00:10:04.700 --> 00:10:07.090 align:start position:0% +die Menschen, die damals hier gelebt haben? +Leider<00:10:05.100> nicht<00:10:05.500> viel.<00:10:05.900> Sie<00:10:06.300> konnten<00:10:06.700> nicht + +00:10:07.090 --> 00:10:07.100 align:start position:0% +Leider nicht viel. Sie konnten nicht + + +00:10:07.100 --> 00:10:09.090 align:start position:0% +Leider nicht viel. Sie konnten nicht +schreiben,<00:10:07.500> und<00:10:07.900> so<00:10:08.300> haben<00:10:08.700> sie + +00:10:09.090 --> 00:10:09.100 align:start position:0% +schreiben, und so haben sie + + +00:10:09.100 --> 00:10:11.890 align:start position:0% +schreiben, und so haben sie +uns<00:10:09.500> keine<00:10:09.900> Briefe<00:10:10.300> oder<00:10:10.700> Tagebücher<00:10:11.100> hinterlassen.<00:10:11.500> Was + +00:10:11.890 --> 00:10:11.900 align:start position:0% +uns keine Briefe oder Tagebücher hinterlassen. Was + + +00:10:11.900 --> 00:10:14.290 align:start position:0% +uns keine Briefe oder Tagebücher hinterlassen. Was +wir<00:10:12.300> wissen,<00:10:12.700> stammt<00:10:13.100> aus<00:10:13.500> Abgaberegistern,<00:10:13.900> aus + +00:10:14.290 --> 00:10:14.300 align:start position:0% +wir wissen, stammt aus Abgaberegistern, aus + + +00:10:14.300 --> 00:10:17.490 align:start position:0% +wir wissen, stammt aus Abgaberegistern, aus +Gerichtsakten<00:10:14.700> und<00:10:15.100> aus<00:10:15.500> Kirchenbüchern.<00:10:15.900> Daraus<00:10:16.300> können<00:10:16.700> wir<00:10:17.100> aber + +00:10:17.490 --> 00:10:17.500 align:start position:0% +Gerichtsakten und aus Kirchenbüchern. Daraus können wir aber + + +00:10:17.500 --> 00:10:18.690 align:start position:0% +Gerichtsakten und aus Kirchenbüchern. Daraus können wir aber +erstaunlich<00:10:17.900> viel<00:10:18.300> ablesen. + +00:10:18.690 --> 00:10:18.700 align:start position:0% +erstaunlich viel ablesen. + + +00:10:18.700 --> 00:10:20.290 align:start position:0% +erstaunlich viel ablesen. +Wir<00:10:19.100> wissen<00:10:19.500> z.<00:10:19.900> B., + +00:10:20.290 --> 00:10:20.300 align:start position:0% +Wir wissen z. B., + + +00:10:20.300 --> 00:10:23.090 align:start position:0% +Wir wissen z. B., +dass<00:10:20.700> im<00:10:21.100> Jahr<00:10:21.500> 1580<00:10:21.900> in<00:10:22.300> Auen<00:10:22.700> Tal + +00:10:23.090 --> 00:10:23.100 align:start position:0% +dass im Jahr 1580 in Auen Tal + + +00:10:23.100 --> 00:10:25.490 align:start position:0% +dass im Jahr 1580 in Auen Tal +elf<00:10:23.500> Familien<00:10:23.900> lebten.<00:10:24.300> Wir<00:10:24.700> wissen,<00:10:25.100> dass + +00:10:25.490 --> 00:10:25.500 align:start position:0% +elf Familien lebten. Wir wissen, dass + + +00:10:25.500 --> 00:10:27.490 align:start position:0% +elf Familien lebten. Wir wissen, dass +sie<00:10:25.900> vor<00:10:26.300> allem<00:10:26.700> Roggen<00:10:27.100> und + +00:10:27.490 --> 00:10:27.500 align:start position:0% +sie vor allem Roggen und + + +00:10:27.500 --> 00:10:30.290 align:start position:0% +sie vor allem Roggen und +Hafer<00:10:27.900> anbauten.<00:10:28.300> Wir<00:10:28.700> wissen,<00:10:29.100> dass<00:10:29.500> es<00:10:29.900> im + +00:10:30.290 --> 00:10:30.300 align:start position:0% +Hafer anbauten. Wir wissen, dass es im + + +00:10:30.300 --> 00:10:32.690 align:start position:0% +Hafer anbauten. Wir wissen, dass es im +Jahr<00:10:30.700> 1636<00:10:31.100> eine<00:10:31.500> schwere<00:10:31.900> Pest<00:10:32.300> gab, + +00:10:32.690 --> 00:10:32.700 align:start position:0% +Jahr 1636 eine schwere Pest gab, + + +00:10:32.700 --> 00:10:35.890 align:start position:0% +Jahr 1636 eine schwere Pest gab, +an<00:10:33.100> der<00:10:33.500> fast<00:10:33.900> die<00:10:34.300> Hälfte<00:10:34.700> der<00:10:35.100> Menschen<00:10:35.500> starb. + +00:10:35.890 --> 00:10:35.900 align:start position:0% +an der fast die Hälfte der Menschen starb. + + +00:10:35.900 --> 00:10:38.290 align:start position:0% +an der fast die Hälfte der Menschen starb. +Und<00:10:36.300> wir<00:10:36.700> wissen,<00:10:37.100> dass<00:10:37.500> der<00:10:37.900> Ort + +00:10:38.290 --> 00:10:38.300 align:start position:0% +Und wir wissen, dass der Ort + + +00:10:38.300 --> 00:10:39.890 align:start position:0% +Und wir wissen, dass der Ort +sich<00:10:38.700> danach<00:10:39.100> nur<00:10:39.500> langsam + +00:10:39.890 --> 00:10:39.900 align:start position:0% +sich danach nur langsam + + +00:10:39.900 --> 00:10:40.690 align:start position:0% +sich danach nur langsam +erholt<00:10:40.300> hat. + +00:10:40.690 --> 00:10:40.700 align:start position:0% +erholt hat. + + +00:10:40.700 --> 00:10:43.090 align:start position:0% +erholt hat. +Ein<00:10:41.100> besonderer<00:10:41.500> Fund<00:10:41.900> ist<00:10:42.300> ein<00:10:42.700> Gerichtsprotokoll + +00:10:43.090 --> 00:10:43.100 align:start position:0% +Ein besonderer Fund ist ein Gerichtsprotokoll + + +00:10:43.100 --> 00:10:45.090 align:start position:0% +Ein besonderer Fund ist ein Gerichtsprotokoll +aus<00:10:43.500> dem<00:10:43.900> Jahr<00:10:44.300> 1712.<00:10:44.700> Darin + +00:10:45.090 --> 00:10:45.100 align:start position:0% +aus dem Jahr 1712. Darin + + +00:10:45.100 --> 00:10:47.890 align:start position:0% +aus dem Jahr 1712. Darin +klagt<00:10:45.500> ein<00:10:45.900> Müller<00:10:46.300> namens<00:10:46.700> Kaspar<00:10:47.100> Ols<00:10:47.500> Hausen + +00:10:47.890 --> 00:10:47.900 align:start position:0% +klagt ein Müller namens Kaspar Ols Hausen + + +00:10:47.900 --> 00:10:50.290 align:start position:0% +klagt ein Müller namens Kaspar Ols Hausen +gegen<00:10:48.300> seinen<00:10:48.700> Nachbarn,<00:10:49.100> weil<00:10:49.500> dessen<00:10:49.900> Ziegen + +00:10:50.290 --> 00:10:50.300 align:start position:0% +gegen seinen Nachbarn, weil dessen Ziegen + + +00:10:50.300 --> 00:10:53.490 align:start position:0% +gegen seinen Nachbarn, weil dessen Ziegen +immer<00:10:50.700> wieder<00:10:51.100> in<00:10:51.500> seinen<00:10:51.900> Garten<00:10:52.300> eingedrungen<00:10:52.700> seien.<00:10:53.100> Das + +00:10:53.490 --> 00:10:53.500 align:start position:0% +immer wieder in seinen Garten eingedrungen seien. Das + + +00:10:53.500 --> 00:10:55.890 align:start position:0% +immer wieder in seinen Garten eingedrungen seien. Das +Gericht<00:10:53.900> gab<00:10:54.300> dem<00:10:54.700> Müller<00:10:55.100> recht.<00:10:55.500> Der + +00:10:55.890 --> 00:10:55.900 align:start position:0% +Gericht gab dem Müller recht. Der + + +00:10:55.900 --> 00:10:57.490 align:start position:0% +Gericht gab dem Müller recht. Der +Nachbar<00:10:56.300> musste<00:10:56.700> einen<00:10:57.100> Zaun + +00:10:57.490 --> 00:10:57.500 align:start position:0% +Nachbar musste einen Zaun + + +00:10:57.500 --> 00:11:00.290 align:start position:0% +Nachbar musste einen Zaun +bauen<00:10:57.900> und<00:10:58.300> zwei<00:10:58.700> Hühner<00:10:59.100> als<00:10:59.500> Entschädigung<00:10:59.900> zahlen. + +00:11:00.290 --> 00:11:00.300 align:start position:0% +bauen und zwei Hühner als Entschädigung zahlen. + + +00:11:00.300 --> 00:11:03.290 align:start position:0% +bauen und zwei Hühner als Entschädigung zahlen. +[lachen] + +00:11:03.290 --> 00:11:03.300 align:start position:0% +[lachen] + + +00:11:03.300 --> 00:11:05.690 align:start position:0% +[lachen] +Ich<00:11:03.700> erzähle<00:11:04.100> Ihnen<00:11:04.500> das<00:11:04.900> nicht<00:11:05.300> nur, + +00:11:05.690 --> 00:11:05.700 align:start position:0% +Ich erzähle Ihnen das nicht nur, + + +00:11:05.700 --> 00:11:07.690 align:start position:0% +Ich erzähle Ihnen das nicht nur, +weil<00:11:06.100> es<00:11:06.500> lustig<00:11:06.900> ist.<00:11:07.300> Ich + +00:11:07.690 --> 00:11:07.700 align:start position:0% +weil es lustig ist. Ich + + +00:11:07.700 --> 00:11:10.490 align:start position:0% +weil es lustig ist. Ich +erzähle<00:11:08.100> es,<00:11:08.500> weil<00:11:08.900> es<00:11:09.300> zeigt,<00:11:09.700> dass<00:11:10.100> die + +00:11:10.490 --> 00:11:10.500 align:start position:0% +erzähle es, weil es zeigt, dass die + + +00:11:10.500 --> 00:11:12.890 align:start position:0% +erzähle es, weil es zeigt, dass die +Menschen<00:11:10.900> damals<00:11:11.300> ganz<00:11:11.700> ähnliche<00:11:12.100> Sorgen<00:11:12.500> hatten + +00:11:12.890 --> 00:11:12.900 align:start position:0% +Menschen damals ganz ähnliche Sorgen hatten + + +00:11:12.900 --> 00:11:16.090 align:start position:0% +Menschen damals ganz ähnliche Sorgen hatten +wie<00:11:13.300> wir<00:11:13.700> heute.<00:11:14.100> Es<00:11:14.500> ging<00:11:14.900> um<00:11:15.300> den<00:11:15.700> Garten, + +00:11:16.090 --> 00:11:16.100 align:start position:0% +wie wir heute. Es ging um den Garten, + + +00:11:16.100 --> 00:11:18.490 align:start position:0% +wie wir heute. Es ging um den Garten, +um<00:11:16.500> den<00:11:16.900> Nachbarn,<00:11:17.300> um<00:11:17.700> ein<00:11:18.100> bisschen + +00:11:18.490 --> 00:11:18.500 align:start position:0% +um den Nachbarn, um ein bisschen + + +00:11:18.500 --> 00:11:20.090 align:start position:0% +um den Nachbarn, um ein bisschen +Gerechtigkeit.<00:11:18.900> Der<00:11:19.300> Name<00:11:19.700> Ols + +00:11:20.090 --> 00:11:20.100 align:start position:0% +Gerechtigkeit. Der Name Ols + + +00:11:20.100 --> 00:11:22.890 align:start position:0% +Gerechtigkeit. Der Name Ols +Hausen<00:11:20.500> ist<00:11:20.900> übrigens<00:11:21.300> bis<00:11:21.700> heute<00:11:22.100> im<00:11:22.500> Ort + +00:11:22.890 --> 00:11:22.900 align:start position:0% +Hausen ist übrigens bis heute im Ort + + +00:11:22.900 --> 00:11:25.290 align:start position:0% +Hausen ist übrigens bis heute im Ort +zu<00:11:23.300> finden.<00:11:23.700> Vielleicht<00:11:24.100> ist<00:11:24.500> der<00:11:24.900> Wehrführer + +00:11:25.290 --> 00:11:25.300 align:start position:0% +zu finden. Vielleicht ist der Wehrführer + + +00:11:25.300 --> 00:11:27.290 align:start position:0% +zu finden. Vielleicht ist der Wehrführer +ja<00:11:25.700> ein<00:11:26.100> Nachfahre<00:11:26.500> des<00:11:26.900> Müllers. + +00:11:27.290 --> 00:11:27.300 align:start position:0% +ja ein Nachfahre des Müllers. + + +00:11:27.300 --> 00:11:30.090 align:start position:0% +ja ein Nachfahre des Müllers. +Im<00:11:27.700> neunzehnten<00:11:28.100> Jahrhundert<00:11:28.500> hat<00:11:28.900> sich<00:11:29.300> Auen<00:11:29.700> Tal + +00:11:30.090 --> 00:11:30.100 align:start position:0% +Im neunzehnten Jahrhundert hat sich Auen Tal + + +00:11:30.100 --> 00:11:32.490 align:start position:0% +Im neunzehnten Jahrhundert hat sich Auen Tal +stark<00:11:30.500> verändert.<00:11:30.900> Im<00:11:31.300> Jahr<00:11:31.700> 1868<00:11:32.100> wurde + +00:11:32.490 --> 00:11:32.500 align:start position:0% +stark verändert. Im Jahr 1868 wurde + + +00:11:32.500 --> 00:11:35.690 align:start position:0% +stark verändert. Im Jahr 1868 wurde +die<00:11:32.900> Bahnstrecke<00:11:33.300> nach<00:11:33.700> Linden<00:11:34.100> Brunn<00:11:34.500> gebaut.<00:11:34.900> Plötzlich<00:11:35.300> konnten + +00:11:35.690 --> 00:11:35.700 align:start position:0% +die Bahnstrecke nach Linden Brunn gebaut. Plötzlich konnten + + +00:11:35.700 --> 00:11:38.090 align:start position:0% +die Bahnstrecke nach Linden Brunn gebaut. Plötzlich konnten +die<00:11:36.100> Bauern<00:11:36.500> ihre<00:11:36.900> Waren<00:11:37.300> in<00:11:37.700> die + +00:11:38.090 --> 00:11:38.100 align:start position:0% +die Bauern ihre Waren in die + + +00:11:38.100 --> 00:11:39.690 align:start position:0% +die Bauern ihre Waren in die +Stadt<00:11:38.500> bringen.<00:11:38.900> Es<00:11:39.300> entstanden + +00:11:39.690 --> 00:11:39.700 align:start position:0% +Stadt bringen. Es entstanden + + +00:11:39.700 --> 00:11:42.490 align:start position:0% +Stadt bringen. Es entstanden +eine<00:11:40.100> Ziegelei<00:11:40.500> und<00:11:40.900> eine<00:11:41.300> kleine<00:11:41.700> Weberei.<00:11:42.100> Die + +00:11:42.490 --> 00:11:42.500 align:start position:0% +eine Ziegelei und eine kleine Weberei. Die + + +00:11:42.500 --> 00:11:44.890 align:start position:0% +eine Ziegelei und eine kleine Weberei. Die +Einwohnerzahl<00:11:42.900> hat<00:11:43.300> sich<00:11:43.700> in<00:11:44.100> wenigen<00:11:44.500> Jahrzehnten + +00:11:44.890 --> 00:11:44.900 align:start position:0% +Einwohnerzahl hat sich in wenigen Jahrzehnten + + +00:11:44.900 --> 00:11:45.290 align:start position:0% +Einwohnerzahl hat sich in wenigen Jahrzehnten +verdoppelt. + +00:11:45.290 --> 00:11:45.300 align:start position:0% +verdoppelt. + + +00:11:45.300 --> 00:11:48.090 align:start position:0% +verdoppelt. +Das<00:11:45.700> zwanzigste<00:11:46.100> Jahrhundert<00:11:46.500> war<00:11:46.900> auch<00:11:47.300> hier<00:11:47.700> eine + +00:11:48.090 --> 00:11:48.100 align:start position:0% +Das zwanzigste Jahrhundert war auch hier eine + + +00:11:48.100 --> 00:11:50.490 align:start position:0% +Das zwanzigste Jahrhundert war auch hier eine +Zeit<00:11:48.500> der<00:11:48.900> Brüche.<00:11:49.300> Zwei<00:11:49.700> Weltkriege<00:11:50.100> haben + +00:11:50.490 --> 00:11:50.500 align:start position:0% +Zeit der Brüche. Zwei Weltkriege haben + + +00:11:50.500 --> 00:11:53.690 align:start position:0% +Zeit der Brüche. Zwei Weltkriege haben +viele<00:11:50.900> Familien<00:11:51.300> getroffen.<00:11:51.700> Auf<00:11:52.100> dem<00:11:52.500> Friedhof<00:11:52.900> erinnert<00:11:53.300> ein + +00:11:53.690 --> 00:11:53.700 align:start position:0% +viele Familien getroffen. Auf dem Friedhof erinnert ein + + +00:11:53.700 --> 00:11:56.090 align:start position:0% +viele Familien getroffen. Auf dem Friedhof erinnert ein +Denkmal<00:11:54.100> an<00:11:54.500> die<00:11:54.900> Gefallenen.<00:11:55.300> Nach<00:11:55.700> dem + +00:11:56.090 --> 00:11:56.100 align:start position:0% +Denkmal an die Gefallenen. Nach dem + + +00:11:56.100 --> 00:11:57.690 align:start position:0% +Denkmal an die Gefallenen. Nach dem +2.<00:11:56.500> Weltkrieg<00:11:56.900> kamen<00:11:57.300> viele + +00:11:57.690 --> 00:11:57.700 align:start position:0% +2. Weltkrieg kamen viele + + +00:11:57.700 --> 00:12:00.490 align:start position:0% +2. Weltkrieg kamen viele +Vertriebene<00:11:58.100> in<00:11:58.500> den<00:11:58.900> Ort.<00:11:59.300> Sie<00:11:59.700> mussten<00:12:00.100> untergebracht + +00:12:00.490 --> 00:12:00.500 align:start position:0% +Vertriebene in den Ort. Sie mussten untergebracht + + +00:12:00.500 --> 00:12:02.890 align:start position:0% +Vertriebene in den Ort. Sie mussten untergebracht +werden,<00:12:00.900> oft<00:12:01.300> in<00:12:01.700> sehr<00:12:02.100> engen<00:12:02.500> Verhältnissen. + +00:12:02.890 --> 00:12:02.900 align:start position:0% +werden, oft in sehr engen Verhältnissen. + + +00:12:02.900 --> 00:12:04.890 align:start position:0% +werden, oft in sehr engen Verhältnissen. +Für<00:12:03.300> die<00:12:03.700> Alteingesessenen<00:12:04.100> war<00:12:04.500> das + +00:12:04.890 --> 00:12:04.900 align:start position:0% +Für die Alteingesessenen war das + + +00:12:04.900 --> 00:12:07.690 align:start position:0% +Für die Alteingesessenen war das +nicht<00:12:05.300> leicht,<00:12:05.700> und<00:12:06.100> für<00:12:06.500> die<00:12:06.900> Neuen<00:12:07.300> noch + +00:12:07.690 --> 00:12:07.700 align:start position:0% +nicht leicht, und für die Neuen noch + + +00:12:07.700 --> 00:12:08.090 align:start position:0% +nicht leicht, und für die Neuen noch +weniger. + +00:12:08.090 --> 00:12:08.100 align:start position:0% +weniger. + + +00:12:08.100 --> 00:12:11.290 align:start position:0% +weniger. +Aber<00:12:08.500> auch<00:12:08.900> hier<00:12:09.300> hat<00:12:09.700> sich<00:12:10.100> gezeigt,<00:12:10.500> was<00:12:10.900> die + +00:12:11.290 --> 00:12:11.300 align:start position:0% +Aber auch hier hat sich gezeigt, was die + + +00:12:11.300 --> 00:12:13.690 align:start position:0% +Aber auch hier hat sich gezeigt, was die +Bürgermeisterin<00:12:11.700> vorhin<00:12:12.100> beschrieben<00:12:12.500> hat.<00:12:12.900> Mit<00:12:13.300> der + +00:12:13.690 --> 00:12:13.700 align:start position:0% +Bürgermeisterin vorhin beschrieben hat. Mit der + + +00:12:13.700 --> 00:12:15.290 align:start position:0% +Bürgermeisterin vorhin beschrieben hat. Mit der +Zeit<00:12:14.100> sind<00:12:14.500> die<00:12:14.900> Neuen + +00:12:15.290 --> 00:12:15.300 align:start position:0% +Zeit sind die Neuen + + +00:12:15.300 --> 00:12:18.090 align:start position:0% +Zeit sind die Neuen +zu<00:12:15.700> Nachbarn<00:12:16.100> geworden.<00:12:16.500> Sie<00:12:16.900> haben<00:12:17.300> Häuser<00:12:17.700> gebaut, + +00:12:18.090 --> 00:12:18.100 align:start position:0% +zu Nachbarn geworden. Sie haben Häuser gebaut, + + +00:12:18.100 --> 00:12:20.490 align:start position:0% +zu Nachbarn geworden. Sie haben Häuser gebaut, +Vereine<00:12:18.500> gegründet<00:12:18.900> und<00:12:19.300> Familien<00:12:19.700> gegründet.<00:12:20.100> Heute + +00:12:20.490 --> 00:12:20.500 align:start position:0% +Vereine gegründet und Familien gegründet. Heute + + +00:12:20.500 --> 00:12:22.490 align:start position:0% +Vereine gegründet und Familien gegründet. Heute +weiß<00:12:20.900> kaum<00:12:21.300> noch<00:12:21.700> jemand,<00:12:22.100> wessen + +00:12:22.490 --> 00:12:22.500 align:start position:0% +weiß kaum noch jemand, wessen + + +00:12:22.500 --> 00:12:25.290 align:start position:0% +weiß kaum noch jemand, wessen +Großeltern<00:12:22.900> damals<00:12:23.300> gekommen<00:12:23.700> sind<00:12:24.100> und<00:12:24.500> wessen<00:12:24.900> Großeltern + +00:12:25.290 --> 00:12:25.300 align:start position:0% +Großeltern damals gekommen sind und wessen Großeltern + + +00:12:25.300 --> 00:12:26.890 align:start position:0% +Großeltern damals gekommen sind und wessen Großeltern +schon<00:12:25.700> immer<00:12:26.100> hier<00:12:26.500> waren. + +00:12:26.890 --> 00:12:26.900 align:start position:0% +schon immer hier waren. + + +00:12:26.900 --> 00:12:30.090 align:start position:0% +schon immer hier waren. +Liebe<00:12:27.300> Gäste,<00:12:27.700> Archive<00:12:28.100> sind<00:12:28.500> keine<00:12:28.900> staubigen<00:12:29.300> Orte.<00:12:29.700> Sie + +00:12:30.090 --> 00:12:30.100 align:start position:0% +Liebe Gäste, Archive sind keine staubigen Orte. Sie + + +00:12:30.100 --> 00:12:32.490 align:start position:0% +Liebe Gäste, Archive sind keine staubigen Orte. Sie +sind<00:12:30.500> das<00:12:30.900> Gedächtnis<00:12:31.300> einer<00:12:31.700> Gemeinschaft.<00:12:32.100> Und + +00:12:32.490 --> 00:12:32.500 align:start position:0% +sind das Gedächtnis einer Gemeinschaft. Und + + +00:12:32.500 --> 00:12:34.090 align:start position:0% +sind das Gedächtnis einer Gemeinschaft. Und +dieses<00:12:32.900> Gedächtnis<00:12:33.300> lebt<00:12:33.700> davon, + +00:12:34.090 --> 00:12:34.100 align:start position:0% +dieses Gedächtnis lebt davon, + + +00:12:34.100 --> 00:12:36.890 align:start position:0% +dieses Gedächtnis lebt davon, +dass<00:12:34.500> Menschen<00:12:34.900> etwas<00:12:35.300> hineingeben.<00:12:35.700> Deshalb<00:12:36.100> unterstütze<00:12:36.500> ich + +00:12:36.890 --> 00:12:36.900 align:start position:0% +dass Menschen etwas hineingeben. Deshalb unterstütze ich + + +00:12:36.900 --> 00:12:39.290 align:start position:0% +dass Menschen etwas hineingeben. Deshalb unterstütze ich +den<00:12:37.300> Aufruf<00:12:37.700> der<00:12:38.100> Bürgermeisterin<00:12:38.500> ausdrücklich.<00:12:38.900> Bringen + +00:12:39.290 --> 00:12:39.300 align:start position:0% +den Aufruf der Bürgermeisterin ausdrücklich. Bringen + + +00:12:39.300 --> 00:12:41.290 align:start position:0% +den Aufruf der Bürgermeisterin ausdrücklich. Bringen +Sie<00:12:39.700> Ihre<00:12:40.100> Fotos,<00:12:40.500> Ihre<00:12:40.900> Briefe, + +00:12:41.290 --> 00:12:41.300 align:start position:0% +Sie Ihre Fotos, Ihre Briefe, + + +00:12:41.300 --> 00:12:44.090 align:start position:0% +Sie Ihre Fotos, Ihre Briefe, +Ihre<00:12:41.700> Erinnerungen.<00:12:42.100> Was<00:12:42.500> heute<00:12:42.900> alltäglich<00:12:43.300> erscheint,<00:12:43.700> ist + +00:12:44.090 --> 00:12:44.100 align:start position:0% +Ihre Erinnerungen. Was heute alltäglich erscheint, ist + + +00:12:44.100 --> 00:12:46.490 align:start position:0% +Ihre Erinnerungen. Was heute alltäglich erscheint, ist +in<00:12:44.500> hundert<00:12:44.900> Jahren<00:12:45.300> ein<00:12:45.700> wertvolles<00:12:46.100> Zeugnis. + +00:12:46.490 --> 00:12:46.500 align:start position:0% +in hundert Jahren ein wertvolles Zeugnis. + + +00:12:46.500 --> 00:12:49.690 align:start position:0% +in hundert Jahren ein wertvolles Zeugnis. +Ich<00:12:46.900> habe<00:12:47.300> Ihnen<00:12:47.700> eine<00:12:48.100> kleine<00:12:48.500> Auswahl<00:12:48.900> mitgebracht.<00:12:49.300> Im + +00:12:49.690 --> 00:12:49.700 align:start position:0% +Ich habe Ihnen eine kleine Auswahl mitgebracht. Im + + +00:12:49.700 --> 00:12:52.090 align:start position:0% +Ich habe Ihnen eine kleine Auswahl mitgebracht. Im +Foyer<00:12:50.100> des<00:12:50.500> Rathauses<00:12:50.900> hängen<00:12:51.300> ab<00:12:51.700> heute + +00:12:52.090 --> 00:12:52.100 align:start position:0% +Foyer des Rathauses hängen ab heute + + +00:12:52.100 --> 00:12:53.690 align:start position:0% +Foyer des Rathauses hängen ab heute +Kopien<00:12:52.500> der<00:12:52.900> Urkunde<00:12:53.300> und + +00:12:53.690 --> 00:12:53.700 align:start position:0% +Kopien der Urkunde und + + +00:12:53.700 --> 00:12:56.490 align:start position:0% +Kopien der Urkunde und +einiger<00:12:54.100> anderer<00:12:54.500> Dokumente.<00:12:54.900> Schauen<00:12:55.300> Sie<00:12:55.700> sie<00:12:56.100> sich + +00:12:56.490 --> 00:12:56.500 align:start position:0% +einiger anderer Dokumente. Schauen Sie sie sich + + +00:12:56.500 --> 00:12:58.890 align:start position:0% +einiger anderer Dokumente. Schauen Sie sie sich +gern<00:12:56.900> an.<00:12:57.300> Und<00:12:57.700> wenn<00:12:58.100> Sie<00:12:58.500> Fragen + +00:12:58.890 --> 00:12:58.900 align:start position:0% +gern an. Und wenn Sie Fragen + + +00:12:58.900 --> 00:13:00.890 align:start position:0% +gern an. Und wenn Sie Fragen +haben,<00:12:59.300> sprechen<00:12:59.700> Sie<00:13:00.100> mich<00:13:00.500> an. + +00:13:00.890 --> 00:13:00.900 align:start position:0% +haben, sprechen Sie mich an. + + +00:13:00.900 --> 00:13:03.290 align:start position:0% +haben, sprechen Sie mich an. +Ich<00:13:01.300> bin<00:13:01.700> den<00:13:02.100> ganzen<00:13:02.500> Nachmittag<00:13:02.900> hier. + +00:13:03.290 --> 00:13:03.300 align:start position:0% +Ich bin den ganzen Nachmittag hier. + + +00:13:03.300 --> 00:13:05.690 align:start position:0% +Ich bin den ganzen Nachmittag hier. +Ich<00:13:03.700> wünsche<00:13:04.100> Ihnen<00:13:04.500> ein<00:13:04.900> schönes<00:13:05.300> Fest. + +00:13:05.690 --> 00:13:05.700 align:start position:0% +Ich wünsche Ihnen ein schönes Fest. + + +00:13:05.700 --> 00:13:07.690 align:start position:0% +Ich wünsche Ihnen ein schönes Fest. +Vielen<00:13:06.100> Dank<00:13:06.500> für<00:13:06.900> Ihre<00:13:07.300> Aufmerksamkeit. + +00:13:07.690 --> 00:13:07.700 align:start position:0% +Vielen Dank für Ihre Aufmerksamkeit. + + +00:13:07.700 --> 00:13:10.690 align:start position:0% +Vielen Dank für Ihre Aufmerksamkeit. +[applaus] + +00:13:10.690 --> 00:13:10.700 align:start position:0% +[applaus] + diff --git a/tests/daten/beispiel.glossar.txt b/tests/daten/beispiel.glossar.txt new file mode 100644 index 0000000..e6f6be3 --- /dev/null +++ b/tests/daten/beispiel.glossar.txt @@ -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 diff --git a/tests/test_abschrift_korrigieren.py b/tests/test_abschrift_korrigieren.py index 1bf9e1d..dc074e1 100644 --- a/tests/test_abschrift_korrigieren.py +++ b/tests/test_abschrift_korrigieren.py @@ -11,9 +11,11 @@ import pytest import abschrift_korrigieren as ak REPO = Path(__file__).resolve().parent.parent -SAMPLE = REPO / "testdaten" / "ramstein.de.txt" -GLOSSARY = REPO / "ramstein.glossar.txt" +# Own, made-up sample speech; real speeches are only kept locally in testdaten/ +SAMPLE = REPO / "tests" / "daten" / "beispiel.de.txt" +GLOSSARY = REPO / "tests" / "daten" / "beispiel.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 REAL_FIND_MERGE_SIDE = ak.find_merge_side @@ -117,6 +119,10 @@ def test_build_system_appends_terms(): system = ak.build_system(["Kreml", "Egon Bahr"]) assert system.startswith(ak.SYSTEM) assert "- Kreml\n- Egon Bahr" in system + # The model must not complete names from the glossary + assert "Ergänze keine Vornamen" in system + assert "bleibt es beim Nachnamen" in ak.SYSTEM + assert "keep only the surname" in ak.SYSTEM_EN SAMPLE_GLOSSARIES = [ @@ -126,19 +132,37 @@ SAMPLE_GLOSSARIES = [ ] +# Real speeches and their glossaries are not in the repository; without them these skip +needs_speeches = pytest.mark.skipif( + not all( + (SPEECHES / sample).is_file() and (REPO / glossary).is_file() + for glossary, sample in SAMPLE_GLOSSARIES + ) or not SHARED_GLOSSARY.is_file(), + reason="echte Reden (testdaten/) und ihre Glossare nur lokal", +) + + +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) def test_sample_glossary_replacements_all_match(capsys, glossary, sample): """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]) capsys.readouterr() ak.apply_replacements(text, ak.read_glossary(REPO / glossary)[1]) assert "ohne Treffer" not in capsys.readouterr().out +@needs_speeches def test_shared_glossary_rules_match_some_speech(): texts = [ - flat((REPO / "testdaten" / sample).read_text(encoding="utf-8")) + flat((SPEECHES / sample).read_text(encoding="utf-8")) for _, sample in SAMPLE_GLOSSARIES ] for wrong, right in ak.read_glossary(SHARED_GLOSSARY)[1]: @@ -388,7 +412,7 @@ def test_build_paragraphs_asks_where_short_paragraphs_belong(tmp_path, monkeypat @pytest.fixture def sample_copy(tmp_path): - path = tmp_path / "ramstein.de.txt" + path = tmp_path / "beispiel.de.txt" shutil.copy(SAMPLE, path) return path @@ -396,22 +420,92 @@ def sample_copy(tmp_path): def test_main_default_output_resume_and_glossary(sample_copy, monkeypatch, capsys): monkeypatch.setattr(ak, "correct_chunk", identity_correct) 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") - assert "Ramstein" in result and "Rammstein" not in result - assert "Kreml" in result and "1983" in result - assert (sample_copy.parent / "ramstein.de.korrigiert.parts").is_dir() + assert "Auental" in result and "Auen Tal" not in result + assert "Haberkamp" in result and "1274" in result + assert (sample_copy.parent / "beispiel.de.korrigiert.parts").is_dir() assert "WARNUNG" not in capsys.readouterr().out # Second run: everything cached, no model calls monkeypatch.setattr(ak, "correct_chunk", 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 +def shouting(chunk, index, system): + """A different model result than identity_correct.""" + return chunk.strip().replace("Vielen Dank", "VIELEN DANK") + + +def test_main_overwrites_own_output(sample_copy, monkeypatch, capsys): + monkeypatch.setattr(ak, "correct_chunk", identity_correct) + monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) + run_main(monkeypatch, "-i", sample_copy) + target = sample_copy.with_name("beispiel.de.korrigiert.txt") + + # Unchanged output of the last run is replaced by a different result + monkeypatch.setattr(ak, "correct_chunk", shouting) + run_main(monkeypatch, "-i", sample_copy, "-m", "anderes:modell") + assert "VIELEN DANK" in target.read_text(encoding="utf-8") + assert not ak.new_output_path(target).exists() + assert "WARNUNG" not in capsys.readouterr().out + + +def test_main_keeps_hand_edited_output(sample_copy, monkeypatch, capsys): + monkeypatch.setattr(ak, "correct_chunk", identity_correct) + monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) + run_main(monkeypatch, "-i", sample_copy) + target = sample_copy.with_name("beispiel.de.korrigiert.txt") + edited = target.read_text(encoding="utf-8") + "Von Hand ergänzt.\n" + target.write_text(edited, encoding="utf-8") + capsys.readouterr() + + monkeypatch.setattr(ak, "correct_chunk", shouting) + run_main(monkeypatch, "-i", sample_copy, "-m", "anderes:modell") + + new = sample_copy.with_name("beispiel.de.neu.korrigiert.txt") + assert target.read_text(encoding="utf-8") == edited + assert "VIELEN DANK" in new.read_text(encoding="utf-8") + assert sample_copy.with_name("beispiel.de.neu.aenderungen.html").is_file() + out = capsys.readouterr().out + assert f"WARNUNG: {target} wurde seit dem letzten Lauf geändert" in out + assert f"Fertig: {new}" in out + + # --ueberschreiben replaces the edited file + run_main(monkeypatch, "-i", sample_copy, "-m", "anderes:modell", "--ueberschreiben") + assert "VIELEN DANK" in target.read_text(encoding="utf-8") + + +def test_main_keeps_differing_output_without_checksum(sample_copy, monkeypatch, capsys): + target = sample_copy.with_name("beispiel.de.korrigiert.txt") + target.write_text("Älteres Ergebnis, Herkunft unbekannt.\n", encoding="utf-8") + monkeypatch.setattr(ak, "correct_chunk", identity_correct) + monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) + run_main(monkeypatch, "-i", sample_copy) + + assert target.read_text(encoding="utf-8") == "Älteres Ergebnis, Herkunft unbekannt.\n" + assert sample_copy.with_name("beispiel.de.neu.korrigiert.txt").is_file() + assert "WARNUNG" in capsys.readouterr().out + + +@pytest.mark.parametrize("name, expected", [ + ("rede.korrigiert.txt", "rede.neu.korrigiert.txt"), + ("out.txt", "out.neu.txt"), +]) +def test_new_output_path(name, expected): + assert ak.new_output_path(Path("a") / name) == Path("a") / expected + + +def test_choose_output_same_content_is_no_conflict(tmp_path): + target = tmp_path / "rede.korrigiert.txt" + target.write_text("gleich\n", encoding="utf-8") + assert ak.choose_output(target, "gleich\n", tmp_path / "fehlt.parts") == target + + def test_main_output_option_creates_directories(sample_copy, monkeypatch): monkeypatch.setattr(ak, "correct_chunk", identity_correct) monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) @@ -424,36 +518,36 @@ def test_main_output_option_creates_directories(sample_copy, monkeypatch): def test_main_vtt_input_matches_txt_input(sample_copy, monkeypatch): monkeypatch.setattr(ak, "correct_chunk", identity_correct) 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() shutil.copy(SAMPLE.with_suffix(".vtt"), vtt) run_main(monkeypatch, "-i", sample_copy) run_main(monkeypatch, "-i", vtt) - expected = sample_copy.with_name("ramstein.de.korrigiert.txt") - assert vtt.with_name("ramstein.de.korrigiert.txt").read_text( + expected = sample_copy.with_name("beispiel.de.korrigiert.txt") + assert vtt.with_name("beispiel.de.korrigiert.txt").read_text( encoding="utf-8" ) == expected.read_text(encoding="utf-8") def test_main_writes_change_report(sample_copy, monkeypatch, capsys): 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, "find_paragraph_starts", every_nth_start(5)) run_main(monkeypatch, "-i", sample_copy) - report = sample_copy.with_name("ramstein.de.aenderungen.html") - assert "title='Original: Rammstein" in report.read_text(encoding="utf-8") + report = sample_copy.with_name("beispiel.de.aenderungen.html") + assert "title='Original: Linden Brunn" in report.read_text(encoding="utf-8") out = capsys.readouterr().out - assert "„Rammstein“ → „Ramstein“" in out + assert "„Linden Brunn“ → „Lindenbrunn“" in out assert f"Bericht: {report}" in out def test_main_report_suspects_only_model_changes(sample_copy, monkeypatch, capsys): 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): return chunk.strip().replace(" das ", " dies ", 1) @@ -462,9 +556,9 @@ def test_main_report_suspects_only_model_changes(sample_copy, monkeypatch, capsy monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) 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("

Zu prüfen")[1].split("

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 out = capsys.readouterr().out assert "gültiges Wort ersetzt: „das“ → „dies“" in out @@ -475,7 +569,7 @@ def test_main_without_change_report(sample_copy, monkeypatch): monkeypatch.setattr(ak, "correct_chunk", identity_correct) monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) 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): @@ -488,7 +582,7 @@ def test_main_model_option(sample_copy, monkeypatch): monkeypatch.setattr(ak, "correct_chunk", correct) 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) default_parts = {p.name for p in parts.glob("part*")} @@ -531,9 +625,16 @@ def from_url(fake_yt_dlp, yt_dlp_installed, monkeypatch): monkeypatch.setattr(ak, "find_paragraph_starts", every_nth_start(5)) +def kreml_glossary(folder): + """The one glossary rule the fake video needs.""" + path = folder / "kreml.glossar.txt" + path.write_text("Kremmel => Kreml\n", encoding="utf-8") + return path + + def test_main_url_default_names(from_url, tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) - run_main(monkeypatch, "-u", URL, "-g", SHARED_GLOSSARY) + run_main(monkeypatch, "-u", URL, "-g", kreml_glossary(tmp_path)) raw = (tmp_path / "Kanal_Rede_2026-03-28.txt").read_text(encoding="utf-8") assert raw == "Der Kremmel ist in Moskau.\nDas ist bekannt.\n" @@ -576,6 +677,7 @@ def test_build_system_english(): system = ak.build_system(["Mearsheimer"], "en") assert system.startswith(ak.SYSTEM_EN) assert "Glossary:" in system and "- Mearsheimer" in system + assert "do not add first" in system def test_main_english_prompts(sample_copy, monkeypatch, capsys): @@ -822,7 +924,7 @@ def test_main_url_several_ranges(fake_yt_dlp, yt_dlp_installed, tmp_path, monkey monkeypatch.setattr(subprocess, "run", fake_yt_dlp(VIDEO, vtt=MULTI_VTT)) sent = chunk_recorder(monkeypatch) monkeypatch.chdir(tmp_path) - run_main(monkeypatch, "-u", URL, "-z", "0:00:00-0:00:30 0:02", "-g", SHARED_GLOSSARY) + run_main(monkeypatch, "-u", URL, "-z", "0:00:00-0:00:30 0:02", "-g", kreml_glossary(tmp_path)) name = "Kanal_Rede_2026-03-28_bis_00-00-30+ab_00-02-00" assert (tmp_path / f"{name}.txt").read_text(encoding="utf-8") == ( diff --git a/tests/test_aenderungen.py b/tests/test_aenderungen.py index 49fdfef..ce492dd 100644 --- a/tests/test_aenderungen.py +++ b/tests/test_aenderungen.py @@ -124,8 +124,8 @@ def test_cli_missing_file(tmp_path, monkeypatch, capsys): WORDS = {"professor", "das", "dass", "ist", "haus", "unterschreiben", "bar"} -def suspects(model_input, corrected, wordlist=WORDS, known=()): - found = ae.review_candidates(ae.compare(model_input, corrected), wordlist, set(known)) +def suspects(model_input, corrected, wordlist=WORDS, glossary=(), lang="de"): + found = ae.review_candidates(ae.compare(model_input, corrected), wordlist, glossary, lang) return [(s.reason, s.old, s.new) for s in found] @@ -153,13 +153,37 @@ def test_review_candidates_ignores(model_input, corrected): assert suspects(model_input, corrected) == [] -def test_review_candidates_glossary_words_are_known(): - known = ae.glossary_words(["Egon Bahr"], [("Bars", "Bahrs")]) - assert known == {"egon", "bahr", "bahrs"} - assert suspects("Bar sagte", "Bahr sagte", known=known) == [] +def test_review_candidates_glossary_spellings_are_not_reported(): + glossary = ae.glossary_entries(["Egon Bahr", ""], [("Bars", "Bahrs")]) + assert glossary == {("egon", "bahr"), ("bahrs",)} + assert suspects("Bar sagte", "Bahr sagte", glossary=glossary) == [] assert suspects("Bar sagte", "Bahr sagte") == [(ae.VALID_WORD, "Bar", "Bahr")] +@pytest.mark.parametrize("model_input, corrected, expected", [ + # A common word of a longer entry explains nothing on its own + ("das sagt ihn nicht", "Das sagt Sie nicht.", [(ae.CHANGED_A_LOT, "ihn", "Sie")]), + # Inserted words stay suspect even if they are in the glossary + ("er kam heute", "er ist kam heute", [(ae.INSERTED, "", "ist")]), + ("Dobrind sagte", "Alexander Dobrindt sagte", + [(ae.CHANGED_A_LOT, "Dobrind", "Alexander Dobrindt")]), +]) +def test_review_candidates_glossary_explains_only_spellings(model_input, corrected, expected): + glossary = ae.glossary_entries( + ["Alexander Dobrindt"], [("befinden Sie", "finden Sie"), ("is", "ist")] + ) + assert suspects(model_input, corrected, glossary=glossary) == expected + + +def test_review_candidates_fillers_per_language(): + # "er" and "um" are real German words; in English they are fillers + assert suspects("dann kam er um zu helfen", "Dann kam, zu helfen.") == [ + (ae.DELETED, "er um", "") + ] + english = suspects("so er we um go", "So we go.", lang="en") + assert english == [] + + def test_review_candidates_without_wordlist(): # Similar replacements of real words go unnoticed, the rest still counts assert suspects("Der Professor kam", "Der Professorin kam", wordlist=None) == [] @@ -198,7 +222,7 @@ def test_report_suspects_only_against_model_input(tmp_path, capsys): assert [s.reason for s in comparison.suspects] == [ae.VALID_WORD, ae.DELETED] assert "Zu prüfen (2)" in page assert "Professorin" in section and "Kremmel" not in section - assert "" in page + assert "" in page assert "⚠" in page # Framing changes nothing about the text itself assert report_text(page) == "Der Professorin im Kreml ⚠ dort.".split() @@ -216,6 +240,20 @@ def test_report_without_suspects(tmp_path): assert "Keine auffälligen Änderungen" in suspect_section(target.read_text(encoding="utf-8")) +def test_cli_ignores_time_headers_missing_in_raw(tmp_path, monkeypatch, capsys): + raw = tmp_path / "rede.vtt" + raw.write_text( + "WEBVTT\n\n00:00:01.000 --> 00:00:02.000\ndas Kremmel heute\n", encoding="utf-8" + ) + corrected = tmp_path / "rede.korrigiert.txt" + corrected.write_text("[00:00:01 - 00:00:02]\n\nDas Kreml heute.\n", encoding="utf-8") + monkeypatch.setattr(sys, "argv", ["aenderungen.py", "-a", str(raw), "-b", str(corrected)]) + ae.main() + out = capsys.readouterr().out + assert "Zu prüfen: 0 Stellen" in out + assert "00:00:01" not in out + + def test_cli_glossary(tmp_path, monkeypatch, capsys): raw = tmp_path / "rede.txt" raw.write_text("das Kremmel und\nBar heute\n", encoding="utf-8") @@ -235,3 +273,51 @@ def test_cli_glossary(tmp_path, monkeypatch, capsys): assert "Zu prüfen: 0 Stellen" in out # The report still compares against the raw transcript assert "1× „Kremmel“ → „Kreml“" in out + + +@pytest.mark.parametrize("old, new, expected", [ + ("Punkten", "Punkte", True), + ("das", "dass", True), + ("sehe", "sähe", True), # umlaut + ("sein", "seien", True), # both endings change + ("kommt,", "kommen,", True), # punctuation does not count + ("Professor", "Professorin", False), # "-in" is no inflection + ("geworben", "geworden", False), + ("unterschreiben", "unterscheiden", False), + ("ich", "sich", False), + ("den", "der", False), # stem too short + ("sich dazu", "zu", False), # more than one word +]) +def test_word_form_change(old, new, expected): + assert ae.word_form_change(old.split(), new.split()) is expected + + +def test_word_form_change_english(): + assert ae.word_form_change(["walk"], ["walked"], "en") + assert not ae.word_form_change(["walk"], ["walker"], "en") + + +def test_review_candidates_word_forms(): + words = WORDS | {"punkten", "punkte"} + assert suspects("die Punkten und das", "die Punkte und dass", wordlist=words) == [ + (ae.WORD_FORM, "Punkten", "Punkte"), (ae.WORD_FORM, "das", "dass"), + ] + + +def test_report_and_summary_put_word_forms_last(tmp_path, capsys): + target = tmp_path / "bericht.html" + comparison = ae.write_report( + "das sagte der Professor", "dass sagte der Professorin", target, "rede" + ) + assert [s.reason for s in comparison.suspects] == [ae.WORD_FORM, ae.VALID_WORD] + page = target.read_text(encoding="utf-8") + section = suspect_section(page) + # Meaning change in the main table, the word form in its own group after it + assert section.index("Professorin") < section.index("Wortform geändert (1)") + assert section.index("Wortform geändert (1)") < section.index("dass") + assert "" in page + + ae.print_summary(comparison) + out = capsys.readouterr().out.split("Zu prüfen: ")[1] + assert out.startswith("2 Stellen (davon 1 Wortformen)") + assert out.index("Professorin") < out.index("„das“ → „dass“") diff --git a/tests/test_vtt2txt.py b/tests/test_vtt2txt.py index 69ad399..84abb81 100644 --- a/tests/test_vtt2txt.py +++ b/tests/test_vtt2txt.py @@ -8,8 +8,10 @@ import pytest import vtt2txt REPO = Path(__file__).resolve().parent.parent -SAMPLE_VTT = REPO / "testdaten" / "ramstein.de.vtt" -SAMPLE_TXT = REPO / "testdaten" / "ramstein.de.txt" +# Own, made-up sample speech; real speeches are only kept locally in testdaten/ +SAMPLE_VTT = REPO / "tests" / "daten" / "beispiel.de.vtt" +SAMPLE_TXT = REPO / "tests" / "daten" / "beispiel.de.txt" +SPEECHES = REPO / "testdaten" @pytest.fixture @@ -107,15 +109,27 @@ def test_is_rolling(cues, expected): def test_main_default_output_matches_sample(sample_copy, monkeypatch, capsys): 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 f"Erstellt: {target}" in capsys.readouterr().out -@pytest.mark.parametrize("name", ["ramstein.de", "magdeburg.de-orig", "Lahnstein.de-orig"]) -def test_sample_vtt_gives_sample_txt(name): - vtt = (REPO / "testdaten" / f"{name}.vtt").read_text(encoding="utf-8-sig") - txt = (REPO / "testdaten" / f"{name}.txt").read_text(encoding="utf-8") +def speech(name): + """A real speech, only kept locally (copyright): skipped without it.""" + path = SPEECHES / name + 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() @@ -128,9 +142,9 @@ def test_main_multiple_inputs(sample_copy, monkeypatch): 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")) - 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 assert out.count("Erstellt:") == 2 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: out_dir.mkdir() 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() @@ -176,7 +190,7 @@ def test_main_bad_file_continues_batch(sample_copy, monkeypatch, capsys, content (["-i", "{txt}"], "Keine VTT-Datei"), (["-i", "{vtt}", "{vtt2}", "-o", "{dir}/x.txt"], "muss -o/--output ein Verzeichnis sein"), (["-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"), ]) def test_cli_errors(sample_copy, monkeypatch, capsys, args, message): @@ -366,10 +380,33 @@ def test_vtt_to_text_skips_empty_range(capsys): assert text == "[00:01:40 - 00:01:41]\nErster Satz ist hier." out = capsys.readouterr().out assert "keine Untertitel im Bereich 00:00:00 – 00:00:50" in out - assert "keine Untertitel im Bereich 00:03:20 – Ende" in out + assert "keine Untertitel im Bereich 00:03:20 – Ende (die Untertitel enden bei" in out assert vtt2txt.vtt_to_text(SPEECH, [(200, None)]) == "" +def test_vtt_to_text_notes_range_past_last_caption(capsys): + # "-z 0-05:00" means five hours, not five minutes + text = vtt2txt.vtt_to_text(SPEECH, [(0, 5 * 3600)]) + assert text.startswith("[00:01:40 - ") + out = capsys.readouterr().out + assert "Bereich 00:00:00 – 05:00:00 reicht über das Ende der Untertitel hinaus" in out + assert "Stunden:Minuten, Minute 5 ist 00:05" in out + + +@pytest.mark.parametrize("start, end, expected", [ + (100, 110, ""), # inside + (None, None, ""), + (100, 200, " (die Untertitel enden bei 00:02:00)"), + (150, None, " (die Untertitel enden bei 00:02:00)"), + (0, 3600, " (die Untertitel enden bei 00:02:00; zwei Zahlen wie 05:00 sind " + "Stunden:Minuten, Minute 5 ist 00:05)"), + (0, 200, ""), # no captions at all: no end known +]) +def test_end_hint(start, end, expected): + captions_end = None if (start, end) == (0, 200) else 120 + assert vtt2txt.end_hint(start, end, captions_end) == expected + + def test_vtt_to_text_without_ranges_has_no_header(): assert vtt2txt.vtt_to_text(SPEECH).splitlines()[0] == "Erster Satz ist hier." @@ -394,7 +431,7 @@ def test_split_segments_inverts_join_segments(): def test_main_time_range_default_name(sample_copy, monkeypatch): 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() part = target.read_text(encoding="utf-8").splitlines() assert vtt2txt.HEADER.fullmatch(part[0]) @@ -403,17 +440,17 @@ def test_main_time_range_default_name(sample_copy, monkeypatch): def test_main_several_ranges(sample_copy, monkeypatch): 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")) 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"]]) def test_main_ranges_with_or_without_quotes(sample_copy, monkeypatch, 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() @@ -433,8 +470,8 @@ def test_range_argv(argv, expected): def test_main_range_from_beginning(sample_copy, monkeypatch, ranges): args = ranges if ranges[0].startswith("-z") else ["-z", *ranges] run_main(monkeypatch, "-i", sample_copy, *args) - target = sample_copy.with_name("ramstein.de_bis_00-01-00.txt") - assert target.read_text(encoding="utf-8").startswith("[00:00:09 - ") + target = sample_copy.with_name("beispiel.de_bis_00-01-00.txt") + assert target.read_text(encoding="utf-8").startswith("[00:00:00 - ") def test_main_time_range_without_captions(sample_copy, monkeypatch, capsys): diff --git a/vtt2txt.py b/vtt2txt.py index 4e7f2af..f6c2764 100755 --- a/vtt2txt.py +++ b/vtt2txt.py @@ -307,18 +307,42 @@ def range_label(start, end): return f"{left} – {right}" +def end_hint(start, end, captions_end): + """Note for a range reaching past the last caption, else ""; two numbers + are hours:minutes, so "05:00" for minute 5 is a likely slip.""" + if captions_end is None: + return "" + past_end = (end is not None and end > captions_end) or ( + start is not None and start >= captions_end + ) + if not past_end: + return "" + hint = f" (die Untertitel enden bei {format_time(captions_end)}" + if max(start or 0, end or 0) >= 3600 > captions_end: + hint += "; zwei Zahlen wie 05:00 sind Stunden:Minuten, Minute 5 ist 00:05" + return hint + ")" + + def excerpts(timed, ranges, exact=False): """Return (start, end in seconds, lines) of the text block of each time range. Blocks that overlap after growing to whole sentences are merged; ranges - without captions are skipped with a note. + without captions are skipped with a note, ranges reaching past the last + caption get one. """ + captions_end = max((end for _, end, _ in timed if end is not None), default=None) bounds = [] for start, end in ranges: found = excerpt_bounds(timed, start, end, exact) + hint = end_hint(start, end, captions_end) if found is None: - print(f"Hinweis: keine Untertitel im Bereich {range_label(start, end)}") + print(f"Hinweis: keine Untertitel im Bereich {range_label(start, end)}{hint}") continue + if hint: + print( + f"Hinweis: Bereich {range_label(start, end)} reicht über das Ende " + f"der Untertitel hinaus{hint}" + ) if bounds and found[0] < bounds[-1][1]: bounds[-1] = (bounds[-1][0], max(bounds[-1][1], found[1])) else: