youtube_abschrift_korrigieren/README.md
dschlueter 7bc5e93613 feat: rede_korrigieren.py -m/--model zur Modellwahl
Das Modell steckt in den Cache-Schlüsseln; ein anderes Modell rechnet neu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:54:32 +02:00

10 KiB
Raw Blame History

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

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:

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

./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.de.vtt                    # VTT direkt → rede.de.korrigiert.txt
Option Bedeutung
-i, --input Eingabedatei: Rohabschrift (.txt) oder Untertitel (.vtt, wird wie mit vtt2txt.py umgewandelt), Pflicht
-o, --output Ausgabedatei; Standard: <Eingabe ohne Endung>.korrigiert.txt neben der Eingabe
-g, --glossar Glossar mit festen Ersetzungen und Schreibweisen
-m, --model Ollama-Modell; Standard: qwen3:32b (Konstante MODEL)

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.

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

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 gemeldet (Tippfehler im Glossar). ramstein.glossar.txt und magdeburg.glossar.txt sind Beispiele zu den Testdaten.

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 (mit Glossar ramstein.glossar.txt)
  • magdeburg.de-orig.*: Rede in Magdeburg (mit Glossar magdeburg.glossar.txt)
  • Lahnstein.de-orig.*: Rede „Respekt geht anders“ in Lahnstein (noch ohne Glossar, geladen mit yt_untertitel.py)
./vtt2txt.py -i "testdaten/*.vtt"           # erzeugt alle .txt neu
./rede_korrigieren.py -i testdaten/ramstein.de.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 in den Beispiel-Glossaren trifft ihre Testdaten“), Streaming-Auswertung, Absatzgliederung (Text bleibt unverändert, 3–10 Sätze), Zwischenspeicher/Fortsetzen und die Kommandozeile. 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.