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, Hörfehler, Absätze – möglichst wortgetreu, ohne Zusammenfassung oder Glättung. Das Hauptprogramm ist abschrift_korrigieren.py.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
dschlueter 547dcb358d fix: Originalsprache bei Videos mit KI-synchronisierten Tonspuren
Gefunden mit einem englischen Video (0LmCveTM788): ohne -l wurde Arabisch
gewählt, denn jede der 20 Synchron-Tonspuren hat eine eigene „-orig“-Spur.
- original_language(): aus „language“, sonst Tonspur mit „original“, sonst
  die einzige „-orig“-Spur
- Automatische Untertitel nur in der Originalsprache (keine Synchronisation)
- Sprachen auch mit Region: „en“ findet manuelle Untertitel „en-US“

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:28:05 +02:00
tests fix: Originalsprache bei Videos mit KI-synchronisierten Tonspuren 2026-10-10 20:28:05 +02:00
.gitignore feat: Glossar-Entwurf aus Rohtext und Korrekturlauf (glossar_vorschlag.py) 2026-10-10 20:02:39 +02:00
aenderungen.py feat: Änderungsbericht Rohtext → Korrektur (aenderungen.py) 2026-10-10 19:59:37 +02:00
extract_text.py feat: rede_korrigieren.py -u URL – von YouTube direkt zum korrigierten Text 2026-10-10 20:02:53 +02:00
glossar_vorschlag.py fix: Glossar-Entwurf – alles auskommentiert, Korrekturlauf gegen Rohtext 2026-10-10 20:06:17 +02:00
pytest.ini feat: VTT-Untertitel in Rohabschrift umwandeln (vtt2txt.py) 2026-10-10 17:50:51 +02:00
README.md fix: Originalsprache bei Videos mit KI-synchronisierten Tonspuren 2026-10-10 20:28:05 +02:00
rede_korrigieren.py feat: rede_korrigieren.py -u URL – von YouTube direkt zum korrigierten Text 2026-10-10 20:02:53 +02:00
vtt2txt.py feat: VTT-Untertitel in Rohabschrift umwandeln (vtt2txt.py) 2026-10-10 17:50:51 +02:00
yt_untertitel.py fix: Originalsprache bei Videos mit KI-synchronisierten Tonspuren 2026-10-10 20:28:05 +02:00

youtube_rede_korrigieren

Korrigiert automatische Abschriften deutscher Reden (z. B. YouTube-Untertitel als Text) mit einem lokalen Sprachmodell über Ollama: Rechtschreibung, Satzzeichen, Hörfehler, Absätze – möglichst wortgetreu, ohne Zusammenfassung oder Glättung.

Die Werkzeuge sind einzeln oder hintereinander nutzbar:

Skript Aufgabe
extract_text.py YouTube-URL → Textdatei in einem Schritt (die beiden folgenden zusammen)
yt_untertitel.py Untertitel eines YouTube-Videos als VTT herunterladen
vtt2txt.py VTT in eine Rohabschrift (Text) umwandeln
rede_korrigieren.py Rohabschrift (oder VTT direkt) mit dem Sprachmodell korrigieren
aenderungen.py Änderungsbericht: was hat das Modell gegenüber dem Rohtext geändert?
glossar_vorschlag.py Glossar-Entwurf: vermutete Hörfehler bei Namen und Begriffen

Voraussetzungen

  • Python 3.9+ (nur Standardbibliothek)
  • für den Download: yt-dlp (pip install yt-dlp)
  • Ollama auf 127.0.0.1:11434 mit dem Modell qwen3:32b (ollama pull qwen3:32b)

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

Von der YouTube-URL zum korrigierten Text in einem Befehl:

./rede_korrigieren.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -o lahnstein.korrigiert.txt
# → lahnstein.korrigiert.txt, lahnstein.txt (Rohtext), lahnstein.aenderungen.html

Oder in zwei Schritten, um den Rohtext vorher anzusehen:

./extract_text.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -o lahnstein.txt
./rede_korrigieren.py -i lahnstein.txt          # → lahnstein.korrigiert.txt

Dasselbe in Einzelschritten, wenn die VTT-Datei erhalten bleiben soll:

./yt_untertitel.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ' -n Lahnstein -d testdaten
./vtt2txt.py -i testdaten/Lahnstein.de-orig.vtt
./rede_korrigieren.py -i testdaten/Lahnstein.de-orig.txt

Der Schritt über vtt2txt.py ist optional: rede_korrigieren.py nimmt auch die .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.

./extract_text.py -u 'https://www.youtube.com/watch?v=rm6lADgf6GQ'          # → output.txt
./extract_text.py -u URL -l de -o testdaten/rede.txt                      # Sprache und Ziel
./extract_text.py -u URL -f -o rede.txt                                   # lesbarer Fließtext
./rede_korrigieren.py -i output.txt                                       # → output.korrigiert.txt
Option Bedeutung
-u, --url YouTube-URL, Pflicht
-l, --lang Sprache; Standard: Sprache des Original-Audios (<sprache>-orig)
-o, --output Ausgabedatei (Verzeichnisse werden angelegt, vorhandene Datei überschrieben); Standard: output.txt
-f, --fliesstext Fließtext, auf 80 Zeichen umbrochen (Wörter werden nie getrennt), statt der kurzen Untertitelzeilen; beides versteht rede_korrigieren.py

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.

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.

./yt_untertitel.py -u URL                          # → <Video-ID>.de-orig.vtt
./yt_untertitel.py -u URL -n Lahnstein -d testdaten # → testdaten/Lahnstein.de-orig.vtt
Option Bedeutung
-u, --url YouTube-URL, Pflicht
-n, --name Dateiname ohne Endung; Standard: Video-ID
-l, --lang Sprache; Standard: de
-d, --dir Zielverzeichnis (wird angelegt); Standard: aktuelles Verzeichnis

Eine vorhandene Datei gleichen Namens wird überschrieben.

Untertitel umwandeln: vtt2txt.py

Macht aus VTT-Untertiteln (z. B. von yt-dlp --write-auto-subs) die Rohabschrift für rede_korrigieren.py: Zeitstempel und Tags werden entfernt. YouTube-Auto-Untertitel 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.

./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
Option Bedeutung
-i, --input eine oder mehrere VTT-Dateien oder Muster, Pflicht
-o, --output Ausgabedatei (nur bei einer Eingabedatei) oder Verzeichnis (vorhanden oder mit / am Ende); Standard: <Eingabe ohne Endung>.txt neben der Eingabe

Eine fehlerhafte Datei (keine Untertitel, nicht UTF-8) wird gemeldet, die übrigen werden trotzdem umgewandelt; der Exit-Code ist dann 1.

Abschrift korrigieren: rede_korrigieren.py

./rede_korrigieren.py -i rede.txt                       # → rede.korrigiert.txt
./rede_korrigieren.py -i rede.txt -o out/rede.txt       # eigene Ausgabedatei
./rede_korrigieren.py -i rede.txt -g rede.glossar.txt   # mit Glossar
./rede_korrigieren.py -i rede.txt -g allgemein.glossar.txt -g rede.glossar.txt   # kombiniert
./rede_korrigieren.py -i rede.de.vtt                    # VTT direkt → rede.de.korrigiert.txt
./rede_korrigieren.py -u URL                            # YouTube → <Video-ID>.korrigiert.txt
Option Bedeutung
-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
-l, --lang nur mit -u: Sprache; Standard: Sprache des Original-Audios
-o, --output Ausgabedatei; Standard: <Eingabe ohne Endung>.korrigiert.txt neben der Eingabe, mit -u <Video-ID>.korrigiert.txt
-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

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 am Satzende) und abschnittsweise vom Modell korrigiert. Fortschritt wird live angezeigt.

  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 geteilt, Absätze unter 3 Sätzen mit dem Nachbarn verbunden.

  6. Änderungsbericht: Rohtext (vor dem Glossar) und Ergebnis werden Wort für Wort verglichen, siehe unten.

Zweifelhafte Stellen markiert das Modell als Lesart [prüfen: Originalwortlaut].

Änderungsbericht

Jeder Lauf von rede_korrigieren.py schreibt neben die Ausgabe <Name>.aenderungen.html (aus rede.korrigiert.txt wird rede.aenderungen.html) und zeigt die häufigsten Änderungen in der Konsole. Der Bericht enthält:

  • 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 dahinter, Einfügungen grün, Streichungen rot durchgestrichen, [prüfen: …] orange.

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“.

Für vorhandene Dateien gibt es das eigene Skript:

./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

Glossar

Eine Zeile pro Eintrag, # leitet Kommentare ein:

# feste Ersetzung (ganze Wörter, Groß-/Kleinschreibung zählt, Reihenfolge = Datei)
Willly Brand => Willy Brandt
Kremmel => Kreml

# Hinweis fürs Modell (korrekte Schreibweise, optional mit Erläuterung)
Multi-Domain Task Force
Michael Gorbatschow (Vorname so belassen)

Ersetzungen ohne Treffer werden gesammelt gemeldet. Bei einem Glossar für eine einzelne Rede deutet das auf einen Tippfehler hin, bei einem gemeinsamen Glossar ist es normal.

Mehrere Glossare lassen sich kombinieren: ein gemeinsames für wiederkehrende Namen und Hörfehler eines Redners und eines je Rede. 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.

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 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.

Einträge aus den mit -g angegebenen Glossaren werden vorher angewendet und nicht erneut vorgeschlagen.

./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, Brauchbares ins Glossar der Rede (oder ins gemeinsame) übernehmen. Die Modellantworten werden in <Entwurf>.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):

  • 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)

Alle drei mit dem gemeinsamen krone-schmalz.glossar.txt davor.

./vtt2txt.py -i "testdaten/*.vtt"           # erzeugt alle .txt neu
./rede_korrigieren.py -i testdaten/ramstein.de.txt -g krone-schmalz.glossar.txt -g ramstein.glossar.txt
# → testdaten/ramstein.de.korrigiert.txt (nicht versioniert)

Ein Lauf dauert mit qwen3:32b vollständig auf einer RTX 3090 etwa 6 Minuten.

Tests

python3 -m pytest

Die Tests brauchen kein Ollama: Modellaufrufe werden durch Fakes ersetzt. Geprüft 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 unverändert, 3–10 Sätze), Zwischenspeicher/Fortsetzen 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) und den HTML-Bericht (vollständiger Text, Absätze, Escaping). 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, dazu Muster, Ausgabeverzeichnis und Fehlerfälle.

Zwischenstände

Jeder fertige Abschnitt und jede Absatzgliederung wird in <Ausgabe>.parts/ gespeichert. Ein erneuter Lauf überspringt alles, was schon berechnet ist. Ändern sich Modell (auch per -m), Prompt, Glossar oder Text eines Abschnitts, wird genau dieser Teil neu berechnet. Den Ordner kann man jederzeit löschen.

Einstellungen

Oben in rede_korrigieren.py:

Konstante Standard Bedeutung
MODEL qwen3:32b Ollama-Modell (Standard für -m)
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

  • Das Modell ändert gelegentlich Wörter eigenmächtig, auch sinnverändernd (Magdeburg-Rede ohne Glossar: „Professor“ → „Professorin“, „gedeiliche“ → „geregelte“ statt „gedeihliche“). Stichproben lohnen sich; gefundene Fälle gehören ins Glossar.
  • qwen3:32b ohne Denkmodus erkennt Hörfehler ohne Glossar nur teilweise und setzt kaum [prüfen: …]-Marken. Bekannte Fehler gehören deshalb ins Glossar.
  • Das Verbinden kurzer Absätze achtet nicht auf den Inhalt.
  • 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.
  • Abkürzungen wie „z. B.“ oder „2. Weltkrieg“ können als Satzende gelten; das beeinflusst nur mögliche Absatzgrenzen, nicht den Text.