2026-10-11 20:52:02 +02:00
# youtube_abschrift_korrigieren
2026-10-10 16:50:54 +02:00
2026-10-11 20:52:02 +02:00
Korrigiert automatische Abschriften gesprochener Beiträge – Reden, Vorträge,
Interviews, Videos, auf Deutsch oder Englisch (z. B. YouTube-Untertitel als Text) –
mit einem lokalen Sprachmodell über Ollama: Rechtschreibung, Satzzeichen,
2026-10-10 16:50:54 +02:00
Hörfehler, Absätze – möglichst wortgetreu, ohne Zusammenfassung oder Glättung.
2026-10-11 20:52:02 +02:00
Das Hauptprogramm ist `abschrift_korrigieren.py` .
2026-10-10 16:50:54 +02:00
2026-10-10 19:51:32 +02:00
Die Werkzeuge sind einzeln oder hintereinander nutzbar:
2026-10-10 19:23:28 +02:00
| Skript | Aufgabe |
|---|---|
2026-10-10 19:51:32 +02:00
| `extract_text.py` | YouTube-URL → Textdatei in einem Schritt (die beiden folgenden zusammen) |
2026-10-10 19:23:28 +02:00
| `yt_untertitel.py` | Untertitel eines YouTube-Videos als VTT herunterladen |
| `vtt2txt.py` | VTT in eine Rohabschrift (Text) umwandeln |
2026-10-11 20:52:02 +02:00
| `abschrift_korrigieren.py` | Rohabschrift (oder VTT direkt) mit dem Sprachmodell korrigieren |
2026-10-10 19:59:37 +02:00
| `aenderungen.py` | Änderungsbericht: was hat das Modell gegenüber dem Rohtext geändert? |
2026-10-10 20:02:39 +02:00
| `glossar_vorschlag.py` | Glossar-Entwurf: vermutete Hörfehler bei Namen und Begriffen |
2026-10-10 19:23:28 +02:00
2026-10-10 16:50:54 +02:00
## Voraussetzungen
2026-10-10 18:19:14 +02:00
- Python 3.9+ (nur Standardbibliothek)
- für den Download: [yt-dlp ](https://github.com/yt-dlp/yt-dlp ) (`pip install yt-dlp` )
2026-10-10 16:50:54 +02:00
- Ollama auf `127.0.0.1:11434` mit dem Modell `qwen3:32b`
(`ollama pull qwen3:32b` )
2026-10-11 20:52:02 +02:00
`abschrift_korrigieren.py` und `glossar_vorschlag.py` prüfen beides vor dem Start und
2026-10-11 19:20:46 +02:00
brechen sonst mit einem Hinweis ab (`sudo systemctl start ollama` bzw. `ollama pull …` )
2026-10-11 21:32:06 +02:00
- für den Änderungsbericht eine Wortliste: `/usr/share/dict/ngerman` (Paket `wngerman` ),
für englische Beiträge `/usr/share/dict/american-english` (Paket `wamerican` ).
Fehlt sie, gibt es einen Hinweis und die Prüfung „gültiges Wort ersetzt“ entfällt
2026-10-10 16:50:54 +02:00
Für gute Geschwindigkeit muss das Modell komplett in den Grafikspeicher passen.
Mit `OLLAMA_NUM_PARALLEL=1` braucht `qwen3:32b` bei 16k Kontext rund 24 GB
(eine RTX 3090). Bei `OLLAMA_NUM_PARALLEL=4` landet ein Drittel auf der CPU und
der Lauf wird etwa 12-mal langsamer.
## Aufruf
2026-10-10 20:02:53 +02:00
Von der YouTube-URL zum korrigierten Text in einem Befehl:
```bash
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -o lahnstein.korrigiert.txt
2026-10-10 20:02:53 +02:00
# → lahnstein.korrigiert.txt, lahnstein.txt (Rohtext), lahnstein.aenderungen.html
```
Oder in zwei Schritten, um den Rohtext vorher anzusehen:
2026-10-10 19:51:32 +02:00
```bash
./extract_text.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -o lahnstein.txt
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -i lahnstein.txt # → lahnstein.korrigiert.txt
2026-10-10 19:51:32 +02:00
```
Dasselbe in Einzelschritten, wenn die VTT-Datei erhalten bleiben soll:
2026-10-10 18:19:14 +02:00
```bash
./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d testdaten
./vtt2txt.py -i testdaten/Lahnstein.de-orig.vtt
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -i testdaten/Lahnstein.de-orig.txt
2026-10-10 18:19:14 +02:00
```
2026-10-11 20:52:02 +02:00
Der Schritt über `vtt2txt.py` ist optional: `abschrift_korrigieren.py` nimmt auch die
2026-10-10 19:51:32 +02:00
`.vtt` direkt. Die `.txt` lohnt sich, um den Rohtext anzusehen oder ein Glossar
daraus zu erstellen.
### URL → Text in einem Schritt: `extract_text.py`
Lädt die Untertitel und speichert nur den Text; die VTT-Datei bleibt ein
Zwischenschritt im temporären Verzeichnis. Die Spurwahl ist dieselbe wie bei
`yt_untertitel.py` , nur ist die Standardsprache die des Original-Audios.
```bash
2026-10-10 21:03:14 +02:00
./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
2026-10-10 19:51:32 +02:00
./extract_text.py -u URL -l de -o testdaten/rede.txt # Sprache und Ziel
2026-10-10 19:53:42 +02:00
./extract_text.py -u URL -f -o rede.txt # lesbarer Fließtext
2026-10-11 20:20:54 +02:00
./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
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -i rede.txt # → rede.korrigiert.txt
2026-10-10 19:51:32 +02:00
```
| Option | Bedeutung |
|---|---|
| `-u` , `--url` | YouTube-URL, Pflicht |
| `-l` , `--lang` | Sprache; Standard: Sprache des Original-Audios (`<sprache>-orig` ) |
2026-10-10 21:03:14 +02:00
| `-o` , `--output` | Ausgabedatei (Verzeichnisse werden angelegt, vorhandene Datei überschrieben); Standard: `<Kanal>_<Titel>_<Datum>.txt` , siehe unten |
2026-10-11 20:20:54 +02:00
| `-z` , `--zeitraeume` | nur Untertitel in diesen Bereichen, siehe [Zeitauswahl ](#zeitauswahl--z ) |
2026-10-11 20:12:49 +02:00
| `--exakt` | genau an den Zeiten schneiden statt an Satzgrenzen |
2026-10-11 20:52:02 +02:00
| `-f` , `--fliesstext` | Fließtext, auf 80 Zeichen umbrochen (Wörter werden nie getrennt), statt der kurzen Untertitelzeilen; beides versteht `abschrift_korrigieren.py` |
2026-10-10 19:23:28 +02:00
2026-10-10 21:03:14 +02:00
### Standard-Dateinamen für YouTube-Videos
Ohne `-o` bzw. `-n` bilden `extract_text.py` , `yt_untertitel.py` und
2026-10-11 20:52:02 +02:00
`abschrift_korrigieren.py -u` den Namen aus Kanal, Titel und Hochladedatum:
2026-10-10 21:03:14 +02:00
| Video | Name |
|---|---|
| John Mearsheimer, „Episode 1: Origins of the War In Ukraine“ | `John_Mearsheimer_Offensive_Realism_Episode_1_Origins_of_the_War_In_Ukraine_2026-07-30` |
| GGBLahnstein, „Prof. Gabriele Krone-Schmalz – Respekt geht anders – …“ | `GGBLahnstein_Prof_Gabriele_Krone-Schmalz_Respekt_geht_anders_2026-07-30` |
Wörter werden mit `_` verbunden. Bindestriche und Punkte im Wort bleiben
(„Krone-Schmalz“), andere Zeichen fallen weg. Der Kanal wird auf 40, der Titel auf
60 Zeichen an einer Wortgrenze gekürzt. Ohne verwertbaren Kanal und Titel gilt die
2026-10-11 20:20:54 +02:00
Video-ID. Mit `-z` kommen die Bereiche dazu, z. B.
2026-10-11 20:29:34 +02:00
`…_2026-07-30_00-03-17_bis_00-05-25` (`-z A` : `_ab_…` , `-z 0-B` bzw. `-z -B` : `_bis_…` ;
2026-10-11 20:12:49 +02:00
mehrere Bereiche mit `+` verbunden: `…_00-05-00_bis_00-06-00+ab_00-25-00` ).
2026-10-11 19:07:56 +02:00
Gleiches Video ergibt immer denselben Namen; eine vorhandene Datei wird
2026-10-10 21:03:14 +02:00
überschrieben (ein mit `-u` gespeicherter, abweichender Rohtext aber nie).
2026-10-10 18:19:14 +02:00
### Untertitel herunterladen: `yt_untertitel.py`
Lädt die Untertitel eines YouTube-Videos über `yt-dlp` als VTT-Datei, ohne das
Video selbst. Gewählt wird:
1. manuelle Untertitel in der gewünschten Sprache, sonst
2. automatische Untertitel in der Originalsprache des Videos (`de-orig` ).
Automatische Untertitel ohne `-orig` sind Maschinenübersetzungen aus einer anderen
Sprache und werden nie genommen. Gibt es keine passende Spur, nennt das Skript die
vorhandenen Sprachen.
2026-10-10 20:28:05 +02:00
Videos mit KI-synchronisierten Tonspuren haben für * jede * Synchronsprache eine
`-orig` -Spur. Die Originalsprache kommt deshalb aus den Video-Infos (`language` , sonst
die Tonspur mit dem Vermerk „original“); automatische Untertitel anderer Sprachen
gehören zur Synchronisation und werden nicht genommen. Sprachen werden auch mit
Region gefunden: `-l en` findet manuelle Untertitel `en-US` .
2026-10-10 18:19:14 +02:00
```bash
2026-10-10 21:03:14 +02:00
./yt_untertitel.py -u URL # → <Kanal>_<Titel>_<Datum>.de-orig.vtt
2026-10-10 18:19:14 +02:00
./yt_untertitel.py -u URL -n Lahnstein -d testdaten # → testdaten/Lahnstein.de-orig.vtt
```
| Option | Bedeutung |
|---|---|
| `-u` , `--url` | YouTube-URL, Pflicht |
2026-10-10 21:03:14 +02:00
| `-n` , `--name` | Dateiname ohne Endung; Standard: `<Kanal>_<Titel>_<Datum>` |
2026-10-10 18:19:14 +02:00
| `-l` , `--lang` | Sprache; Standard: `de` |
| `-d` , `--dir` | Zielverzeichnis (wird angelegt); Standard: aktuelles Verzeichnis |
Eine vorhandene Datei gleichen Namens wird überschrieben.
2026-10-10 17:50:51 +02:00
### Untertitel umwandeln: `vtt2txt.py`
Macht aus VTT-Untertiteln (z. B. von `yt-dlp --write-auto-subs` ) die Rohabschrift
2026-10-11 20:52:02 +02:00
für `abschrift_korrigieren.py` : Zeitstempel und Tags werden entfernt. YouTube-Auto-Untertitel
2026-10-10 17:50:51 +02:00
zeigen ein rollendes Fenster, jeder Block wiederholt das Ende des vorigen. Übernommen
wird nur, was nach dieser Überlappung neu ist; sagt der Redner eine Zeile wirklich
zweimal, bleibt sie zweimal erhalten.
```bash
./vtt2txt.py -i rede.de.vtt # → rede.de.txt
./vtt2txt.py -i ramstein.de*.vtt # mehrere Dateien, je → *.txt
./vtt2txt.py -i "ramstein.de*.vtt" # Muster löst das Programm auf (Windows)
./vtt2txt.py -i rede.de.vtt -o out/rede.txt # eigene Ausgabedatei
./vtt2txt.py -i *.vtt -o out/ # alle in ein Verzeichnis
2026-10-11 20:20:54 +02:00
./vtt2txt.py -i rede.de.vtt -z 0:03:17-0:05:25 # Ausschnitt → rede.de_00-03-17_bis_00-05-25.txt
./vtt2txt.py -i rede.de.vtt -z 00:05-00:06 00:25 # mehrere Bereiche in einer Datei
2026-10-10 17:50:51 +02:00
```
| Option | Bedeutung |
|---|---|
| `-i` , `--input` | eine oder mehrere VTT-Dateien oder Muster, Pflicht |
2026-10-11 20:20:54 +02:00
| `-o` , `--output` | Ausgabedatei (nur bei einer Eingabedatei) oder Verzeichnis (vorhanden oder mit `/` am Ende); Standard: `<Eingabe ohne Endung>.txt` neben der Eingabe, mit `-z` zusätzlich die Bereiche im Namen |
| `-z` , `--zeitraeume` | nur Untertitel in diesen Bereichen, siehe unten |
2026-10-11 20:12:49 +02:00
| `--exakt` | genau an den Zeiten schneiden, auch mitten im Satz |
2026-10-11 19:34:36 +02:00
2026-10-11 20:20:54 +02:00
#### Zeitauswahl (`-z`)
2026-10-11 20:12:49 +02:00
2026-10-11 20:52:02 +02:00
Gilt gleich für `vtt2txt.py` , `extract_text.py` und `abschrift_korrigieren.py` .
2026-10-11 20:12:49 +02:00
| Zeit | Bedeutung |
|---|---|
| `00:05:10` | Stunden:Minuten:Sekunden (auch `00:5:10` , Sekunden mit Nachkommastellen) |
| `00:20` | Stunden:Minuten, also Minute 20 |
| `25` | Minute 25 |
| Aufruf | Text |
|---|---|
2026-10-11 20:20:54 +02:00
| `-z 00:05:10` | ab 5:10 bis zum Ende des Videos |
2026-10-11 20:29:34 +02:00
| `-z 0-00:20` oder `-z -00:20` | vom Anfang bis Minute 20 |
2026-10-11 20:20:54 +02:00
| `-z 00:05-00:06` | von Minute 5 bis Minute 6 |
| `-z 00:5:00-00:6:00 00:10-00:12:00 00:25` | Minute 5– 6, Minute 10– 12 und alles ab Minute 25 |
2026-10-11 20:12:49 +02:00
2026-10-11 20:29:34 +02:00
Ein Bereich ist `A-B` , `A` (ab A bis zum Ende) oder `0-B` bzw. kurz `-B` (vom
Anfang bis B). Mehrere Bereiche werden durch Leerzeichen getrennt, mit oder ohne
2026-10-11 20:20:54 +02:00
Anführungszeichen (`-z "00:05-00:06 00:25"` ist dasselbe). Sie dürfen sich
2026-10-11 20:29:34 +02:00
nicht überschneiden und werden nach der Zeit sortiert.
2026-10-11 20:12:49 +02:00
Alle Bereiche landen in **einer ** Datei. Vor jedem Bereich steht eine Überschrift
mit seinen tatsächlichen Zeiten:
```text
[00:04:57 - 00:06:04]
Ihr seht, es gibt keinen einzigen Dialog …
[00:09:58 - 00:12:03]
Also, wenn ihr Programme baut mit Claude Code, …
```
Angeschnittene Sätze werden an beiden Enden vollständig aufgenommen. Der
Ausschnitt beginnt nach dem letzten Satzende vor dem Start und endet mit dem
ersten Satzende nach dem Ende, höchstens 30 Sekunden darüber hinaus
(`MAX_SNAP_SECONDS` ). Liegt kein Satzende in Reichweite, wird an dieser Seite
genau geschnitten (`--exakt` schneidet immer genau).
Die Zeiten der Überschrift sind die Start- und Endzeit der ersten bzw. letzten
Untertitelzeile, also auf wenige Sekunden genau. Überschneiden sich zwei
Bereiche erst durch die Satz-Erweiterung, werden sie zu einem Block
zusammengefasst. Bereiche ohne Untertitel werden mit einem Hinweis übersprungen.
Der Dateiname enthält immer die angegebenen Zeiten.
2026-10-10 17:50:51 +02:00
Eine fehlerhafte Datei (keine Untertitel, nicht UTF-8) wird gemeldet, die übrigen
werden trotzdem umgewandelt; der Exit-Code ist dann 1.
2026-10-11 20:52:02 +02:00
### Abschrift korrigieren: `abschrift_korrigieren.py`
2026-10-10 17:50:51 +02:00
2026-10-10 16:50:54 +02:00
```bash
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -i rede.txt # → rede.korrigiert.txt
./abschrift_korrigieren.py -i rede.txt -o out/rede.txt # eigene Ausgabedatei
./abschrift_korrigieren.py -i rede.txt -g rede.glossar.txt # mit Glossar
./abschrift_korrigieren.py -i rede.txt -g allgemein.glossar.txt -g rede.glossar.txt # kombiniert
./abschrift_korrigieren.py -i rede.de.vtt # VTT direkt → rede.de.korrigiert.txt
./abschrift_korrigieren.py -u URL # YouTube → <Kanal>_<Titel>_<Datum>.korrigiert.txt
./abschrift_korrigieren.py -i talk.txt -l en # englischer Beitrag
./abschrift_korrigieren.py -u URL -z 0:03:17-0:05:25 # nur ein Ausschnitt des Videos
./abschrift_korrigieren.py -u URL -z 00:05-00:06 00:25 # mehrere Bereiche, eine Datei
2026-10-10 16:50:54 +02:00
```
| Option | Bedeutung |
|---|---|
2026-10-10 20:02:53 +02:00
| `-i` , `--input` | Eingabedatei: Rohabschrift (`.txt` ) oder Untertitel (`.vtt` , wird wie mit `vtt2txt.py` umgewandelt) |
| `-u` , `--url` | statt `-i` : YouTube-URL; Untertitel wie bei `extract_text.py` . Der Rohtext wird neben der Ausgabe gespeichert (`rede.korrigiert.txt` → `rede.txt` , sonst `<Name>.roh.txt` ), eine vorhandene, abweichende Datei aber nie überschrieben |
2026-10-11 20:52:02 +02:00
| `-l` , `--lang` | Sprache des Beitrags: `de` oder `en` (auch mit Region, z. B. `en-US` ); wählt Prompts und Prüfmarke. Mit `-u` zugleich die Sprache der Untertitel. Standard: `de` , mit `-u` die Sprache des Original-Audios |
2026-10-11 20:20:54 +02:00
| `-o` , `--output` | Ausgabedatei; Standard: `<Eingabe ohne Endung>.korrigiert.txt` neben der Eingabe, mit `-u` `<Kanal>_<Titel>_<Datum>.korrigiert.txt` ; mit `-z` zusätzlich die Bereiche im Namen |
| `-z` , `--zeitraeume` | nur diese Bereiche korrigieren, siehe [Zeitauswahl ](#zeitauswahl--z ); nur mit `.vtt` -Eingabe oder `-u` , da reiner Text keine Zeitstempel hat |
2026-10-11 20:12:49 +02:00
| `--exakt` | genau an den Zeiten schneiden statt an Satzgrenzen |
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
stehen unverändert als eigene Zeilen im Ergebnis. Zusätzlich weist der Prompt das
Modell an, an den Rändern der Ausschnitte nichts zu ergänzen. Eine Rohabschrift
(`.txt` ) mit solchen Überschriften, etwa von `vtt2txt.py -z` , wird ebenso in
Blöcken korrigiert.
2026-10-10 19:56:18 +02:00
| `-g` , `--glossar` | Glossar mit festen Ersetzungen und Schreibweisen; mehrfach angeben zum Kombinieren (Ersetzungen in Reihenfolge der Angabe) |
2026-10-10 19:54:32 +02:00
| `-m` , `--model` | Ollama-Modell; Standard: `qwen3:32b` (Konstante `MODEL` ) |
2026-10-10 19:59:37 +02:00
| `--kein-bericht` | keinen Änderungsbericht schreiben |
2026-10-10 16:50:54 +02:00
## Ablauf
1. **Fließtext: ** Untertitel-Zeilenumbrüche werden entfernt.
2. **Feste Ersetzungen ** aus dem Glossar (`falsch => richtig` ) werden im Rohtext
angewendet, bevor das Modell ihn sieht.
3. **Korrektur: ** Der Text wird in Abschnitte von ca. 1200 Wörtern geteilt (immer
2026-10-11 21:32:23 +02:00
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.
2026-10-10 16:50:54 +02:00
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
Text selbst wird dabei nicht verändert. Absätze über 10 Sätze werden nochmals
2026-10-11 21:32:34 +02:00
geteilt, Absätze unter 3 Sätzen mit einem Nachbarn verbunden. Passt der kurze
Absatz an beide Nachbarn, entscheidet das Modell nach dem Inhalt, ob er den
vorherigen Gedanken abschließt oder den folgenden einleitet.
2026-10-10 16:50:54 +02:00
2026-10-10 19:59:37 +02:00
6. **Änderungsbericht: ** Rohtext (vor dem Glossar) und Ergebnis werden Wort für Wort
verglichen, siehe unten.
2026-10-10 20:40:40 +02:00
Zweifelhafte Stellen markiert das Modell als `Lesart [prüfen: Originalwortlaut]` ,
in englischen Reden als `reading [check: original wording]` .
Englische Reden bekommen eigene, englische Prompts für Korrektur und Absätze
2026-10-11 20:52:02 +02:00
(`SYSTEM_EN` usw. in `abschrift_korrigieren.py` ); dort entfernt das Modell auch die
2026-10-10 20:40:40 +02:00
Sprecherwechsel-Marken `>>` der YouTube-Auto-Untertitel. Weitere Sprachen lassen sich
über das Wörterbuch `PROMPTS` ergänzen.
2026-10-10 16:50:54 +02:00
2026-10-10 19:59:37 +02:00
## Änderungsbericht
2026-10-11 20:52:02 +02:00
Jeder Lauf von `abschrift_korrigieren.py` schreibt neben die Ausgabe
2026-10-10 19:59:37 +02:00
`<Name>.aenderungen.html` (aus `rede.korrigiert.txt` wird `rede.aenderungen.html` )
und zeigt die häufigsten Änderungen in der Konsole. Der Bericht enthält:
2026-10-11 21:32:06 +02:00
- **Zu prüfen:** eigenmächtige Änderungen des Modells, die den Sinn ändern können,
mit Grund und Zusammenhang (siehe unten),
2026-10-10 19:59:37 +02:00
- alle Änderungen nach Häufigkeit (`gedeiliche → gedeihliche` , `∅ → ist` für Einfügungen),
- den korrigierten Text mit seinen Absätzen: ersetzte Wörter gelb mit dem Original
2026-10-11 21:32:06 +02:00
dahinter, Einfügungen grün, Streichungen rot durchgestrichen, `[prüfen: …]` orange,
Stellen „zu prüfen“ rot umrahmt (gestrichene als ⚠, Grund beim Darüberfahren).
2026-10-10 19:59:37 +02:00
Nicht markiert werden Groß-/Kleinschreibung, Satzzeichen (auch eingefügte
Gedankenstriche) und Schreibweisen wie „z.B.“ → „z. B.“. So bleiben die Wortänderungen
übrig, die man prüfen sollte, gerade eigenmächtige wie „gedeiliche“ → „geregelte“.
2026-10-11 21:32:06 +02:00
### Zu prüfen
Verglichen wird hier der Text, den das Modell bekommen hat (nach den festen
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) |
| 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.
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:
2026-10-10 19:59:37 +02:00
```bash
./aenderungen.py -a rede.txt -b rede.korrigiert.txt # → rede.aenderungen.html
./aenderungen.py -a rede.de.vtt -b rede.korrigiert.txt -o bericht.html
2026-10-11 21:32:06 +02:00
./aenderungen.py -a rede.txt -b rede.korrigiert.txt -g krone-schmalz.glossar.txt -g rede.glossar.txt
./aenderungen.py -a talk.txt -b talk.korrigiert.txt -l en # englische Wortliste
2026-10-10 19:59:37 +02:00
```
2026-10-10 16:50:54 +02:00
## Glossar
Eine Zeile pro Eintrag, `#` leitet Kommentare ein:
```text
# feste Ersetzung (ganze Wörter, Groß-/Kleinschreibung zählt, Reihenfolge = Datei)
Willly Brand => Willy Brandt
Kremmel => Kreml
2026-10-10 19:23:28 +02:00
# Hinweis fürs Modell (korrekte Schreibweise, optional mit Erläuterung)
2026-10-10 16:50:54 +02:00
Multi-Domain Task Force
2026-10-10 19:23:28 +02:00
Michael Gorbatschow (Vorname so belassen)
2026-10-10 16:50:54 +02:00
```
2026-10-11 20:52:02 +02:00
Ersetzungen ohne Treffer werden gesammelt gemeldet. Bei einem Glossar für einen
einzelnen Beitrag deutet das auf einen Tippfehler hin, bei einem gemeinsamen Glossar ist
2026-10-10 19:56:18 +02:00
es normal.
Mehrere Glossare lassen sich kombinieren: ein gemeinsames für wiederkehrende Namen
2026-10-11 20:52:02 +02:00
und Hörfehler eines Redners oder Kanals und eines je Beitrag. Beispiel zu den Testdaten:
2026-10-10 20:07:13 +02:00
`krone-schmalz.glossar.txt` (gemeinsam) plus `ramstein.glossar.txt` ,
`magdeburg.glossar.txt` bzw. `lahnstein.glossar.txt` . Das gemeinsame Glossar zuerst angeben, damit seine
2026-10-11 19:22:04 +02:00
Ersetzungen vor den speziellen greifen. Ein weiteres Kanal-Glossar:
`iamfabian.glossar.txt` für Videos über KI-Coding-Tools (Claude Code, Codex, OpenCode …).
2026-10-10 16:50:54 +02:00
2026-10-10 20:02:39 +02:00
### Glossar-Entwurf: `glossar_vorschlag.py`
Ein Glossar von Hand zu erstellen heißt, den ganzen Rohtext zu lesen. Den ersten
Entwurf liefert das Skript:
1. Das Modell sucht abschnittsweise vermutete Hörfehler: Namen, Orte, Fremdwörter,
Fachbegriffe und falsch zusammen- oder getrennt geschriebene Wörter. Behalten werden
2026-10-10 20:06:17 +02:00
nur Funde, die wörtlich im Rohtext stehen; was das Modell für sicher hält, steht
zuerst.
2. Mit `-k` kommen die Wörter dazu, die ein Korrekturlauf geändert hat, ohne das,
was die Glossare ohnehin erledigen. Vieles davon hängt vom Zusammenhang ab
(`das → dass` ), anderes zeigt Fehlgriffe des Modells (`Kremmel → Kremml` ).
Alle Einträge sind als `# ? falsch => richtig` auskommentiert: Auch „sichere“ Funde
des Modells sind oft falsch (Lahnstein: `Deckmäntelchen → Deckmäntel` ), und eine
falsche feste Ersetzung verdirbt den Text unbemerkt. Zum Übernehmen `# ? ` entfernen.
2026-10-10 20:02:39 +02:00
Einträge aus den mit `-g` angegebenen Glossaren werden vorher angewendet und nicht
2026-10-11 20:16:21 +02:00
erneut vorgeschlagen. Zeit-Überschriften von Ausschnitten
2026-10-11 20:20:54 +02:00
(`[00:04:57 - 00:06:04]` , siehe [Zeitauswahl ](#zeitauswahl--z )) werden aus
2026-10-11 20:16:21 +02:00
Roh- und korrigiertem Text entfernt; das Modell bekommt sie nicht zu sehen.
2026-10-10 20:02:39 +02:00
```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
```
| Option | Bedeutung |
|---|---|
| `-i` , `--input` | Rohabschrift (`.txt` oder `.vtt` ), Pflicht |
| `-k` , `--korrigiert` | korrigierter Text eines Laufs (optional) |
| `-g` , `--glossar` | vorhandene Glossare, mehrfach möglich |
| `-o` , `--output` | Entwurf; Standard: `<Eingabe ohne Endung>.glossar.entwurf.txt` |
| `-m` , `--model` | Ollama-Modell; Standard: `qwen3:32b` |
Der Entwurf ist ein Ausgangspunkt, kein fertiges Glossar: jeden Eintrag prüfen,
2026-10-11 20:52:02 +02:00
Brauchbares ins Glossar des Beitrags (oder ins gemeinsame) übernehmen. Die Modellantworten
2026-10-10 20:02:39 +02:00
werden in `<Entwurf>.parts/` zwischengespeichert.
2026-10-10 16:54:00 +02:00
## Testdaten
2026-10-10 18:19:14 +02:00
`testdaten/` enthält drei Reden, jeweils als automatische YouTube-Untertitel
2026-10-10 17:52:56 +02:00
(`.vtt` , Original) und daraus mit `vtt2txt.py` gewonnener Rohtext (`.txt` , Eingabe
für das Programm):
2026-10-10 16:54:00 +02:00
2026-10-10 19:56:18 +02:00
- `ramstein.de.*` : Rede über die US Air Base Ramstein (Glossar `ramstein.glossar.txt` )
- `magdeburg.de-orig.*` : Rede in Magdeburg (Glossar `magdeburg.glossar.txt` )
2026-10-10 20:07:13 +02:00
- `Lahnstein.de-orig.*` : Rede „Respekt geht anders“ in Lahnstein (Glossar
`lahnstein.glossar.txt` , erstellt mit Hilfe von `glossar_vorschlag.py` )
Alle drei mit dem gemeinsamen `krone-schmalz.glossar.txt` davor.
2026-10-10 16:54:00 +02:00
```bash
2026-10-10 17:52:56 +02:00
./vtt2txt.py -i "testdaten/*.vtt" # erzeugt alle .txt neu
2026-10-11 20:52:02 +02:00
./abschrift_korrigieren.py -i testdaten/ramstein.de.txt -g krone-schmalz.glossar.txt -g ramstein.glossar.txt
2026-10-10 16:54:00 +02:00
# → testdaten/ramstein.de.korrigiert.txt (nicht versioniert)
```
Ein Lauf dauert mit `qwen3:32b` vollständig auf einer RTX 3090 etwa 6 Minuten.
2026-10-10 16:57:37 +02:00
## Tests
```bash
python3 -m pytest
```
Die Tests brauchen kein Ollama: Modellaufrufe werden durch Fakes ersetzt. Geprüft
2026-10-10 19:56:18 +02:00
werden Abschnittsbildung, Glossar (inkl. „jede Ersetzung im Glossar einer Rede trifft
diese Rede, jede im gemeinsamen Glossar trifft mindestens eine“), Streaming-Auswertung, Absatzgliederung (Text bleibt
2026-10-10 16:57:37 +02:00
unverändert, 3– 10 Sätze), Zwischenspeicher/Fortsetzen und die Kommandozeile.
2026-10-10 20:02:39 +02:00
`tests/test_glossar_vorschlag.py` prüft Filter (nur Funde im Text, keine bekannten),
Ausgabeformat (gültiges Glossar, Unsicheres auskommentiert) und Zwischenspeicher.
2026-10-10 19:59:37 +02:00
`tests/test_aenderungen.py` prüft den Wortvergleich (Satzzeichen, Groß-/Kleinschreibung
2026-10-11 21:32:06 +02:00
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).
Die Tests nutzen eine kleine eigene Wortliste statt der des Systems.
2026-10-10 19:51:32 +02:00
`tests/test_extract_text.py` prüft den Gesamtablauf URL → Text, Sprachwahl
(Original-Audio, manuell vor automatisch) und Fehlerfälle.
2026-10-10 18:19:14 +02:00
`tests/test_yt_untertitel.py` prüft Spurauswahl, Aufruf von `yt-dlp` und
Fehlerfälle (ohne Netz, `yt-dlp` wird durch Fakes ersetzt).
2026-10-10 17:52:56 +02:00
`tests/test_vtt2txt.py` prüft die VTT-Umwandlung: jede `.vtt` in `testdaten/`
ergibt genau die zugehörige `.txt` , echte Wiederholungen bleiben erhalten,
2026-10-10 17:50:51 +02:00
dazu Muster, Ausgabeverzeichnis und Fehlerfälle.
2026-10-10 16:57:37 +02:00
2026-10-10 16:50:54 +02:00
## Zwischenstände
2026-10-11 21:32:34 +02:00
Jeder fertige Abschnitt, jede Absatzgliederung und jede Entscheidung beim
Verbinden kurzer Absätze wird in `<Ausgabe>.parts/` gespeichert. Ein erneuter
Lauf überspringt alles, was schon berechnet ist.
2026-10-10 19:54:32 +02:00
Ändern sich Modell (auch per `-m` ), Prompt, Glossar oder Text eines Abschnitts, wird genau dieser
2026-10-10 16:50:54 +02:00
Teil neu berechnet. Den Ordner kann man jederzeit löschen.
## Einstellungen
2026-10-11 20:52:02 +02:00
Oben in `abschrift_korrigieren.py` :
2026-10-10 16:50:54 +02:00
| Konstante | Standard | Bedeutung |
|---|---|---|
2026-10-10 19:54:32 +02:00
| `MODEL` | `qwen3:32b` | Ollama-Modell (Standard für `-m` ) |
2026-10-10 16:50:54 +02:00
| `CHUNK_SIZE` | 1200 | Wörter pro Korrekturabschnitt |
| `MAX_WORD_DEVIATION` | 0.05 | Warnschwelle Wortzahl |
| `MAX_PARAGRAPH_SENTENCES` | 10 | längster erlaubter Absatz |
| `MIN_PARAGRAPH_SENTENCES` | 3 | kürzester gewünschter Absatz |
## Bekannte Grenzen
2026-10-10 19:23:28 +02:00
- Das Modell ändert gelegentlich Wörter eigenmächtig, auch sinnverändernd
(Magdeburg-Rede ohne Glossar: „Professor“ → „Professorin“, „gedeiliche“ →
2026-10-11 21:32:06 +02:00
„geregelte“ statt „gedeihliche“). Die Liste „Zu prüfen“ im Bericht findet die
meisten solcher Fälle, aber nicht alle: Ein falsch erkanntes Wort, das das Modell
durch ein ähnliches, aber falsches ersetzt, fällt nicht auf. Gefundene Fälle
2026-10-10 19:23:28 +02:00
gehören ins Glossar.
2026-10-10 16:50:54 +02:00
- `qwen3:32b` ohne Denkmodus erkennt Hörfehler ohne Glossar nur teilweise und
setzt kaum `[prüfen: …]` -Marken. Bekannte Fehler gehören deshalb ins Glossar.
2026-10-10 19:23:28 +02:00
- `vtt2txt.py` erkennt Wiederholungen an der Überlappung aufeinanderfolgender
Untertitel-Blöcke. Bei Untertiteln ohne rollendes Fenster gehen deshalb zwei
direkt aufeinanderfolgende, identische Blöcke zu einem zusammen.
2026-10-11 21:32:23 +02:00
- Einzelbuchstaben und ein- bis zweistellige Zahlen mit Punkt gelten nie als
Satzende („Plan B.“, „Es waren 12.“); das beeinflusst nur mögliche Absatzgrenzen,
nicht den Text.