transkript-erstellen

Wrapper um youtube/scripts/transcribe.py (WhisperX large-v3 deutsch, CPU + int8). Drei Output-Files in youtube/transcripts/<basename>.{txt,srt,json}.

Wann nutzen

VOR dem Cut, sobald ein neuer Take exportiert ist. Output ist Lese-Material zum Clustern + Roh-Daten fuer Frame-genaue Trim-Ranges in Remotion-Compositions.

Wann NICHT nutzen

  • Schon vorhandenes Transkript: pruefe youtube/transcripts/<basename>.{txt,srt,json} zuerst.
  • Englisches Video: Skript ruft language="de" hardcoded — manuell anpassen oder Take ist falsch.

Schritte

1. Pfad bestaetigen + Basename ableiten

Input:    /Users/marvinkuehlmann/source/youtube/footage/extracted-audio/Built-in Retina Display.mp4
Basename: Built-in Retina Display
Output:   youtube/transcripts/Built-in Retina Display.{txt,srt,json}

Wenn der Basename Sonderzeichen hat (Leerzeichen, generisch klingend), Marvin fragen ob Rename okay (z. B. screencast-vlog-mai-v2.mp4). Lieber einmal sauber benennen als spaeter Pfade flicken.

2. Transcribe-Script ausfuehren

cd /Users/marvinkuehlmann/source/youtube
python3 scripts/transcribe.py "<input-pfad>" transcripts
  • Dauer: ~50-80 % der Video-Laenge auf Apple-Silicon-CPU. 11 Min Video → ~6-9 Min Transkript.
  • RAM: ~6-8 GB peak (large-v3 + Alignment-Modell laden).
  • Im Hintergrund laufen lassen (run_in_background=true), Marvin macht parallel was anderes. Status-Update wenn fertig.

3. Output verifizieren

Drei Files muessen existieren:

  • transcripts/<name>.txt — typischerweise 5-30 KB fuer 10-15 Min Audio
  • transcripts/<name>.srt — 8-50 KB
  • transcripts/<name>.json — 300 KB - 2 MB, der dicke (Word-Level)

Wenn .json < 50 KB → Alignment ist gescheitert, nur Segment-Level. Marvin sagen + Re-Run-Option anbieten.

4. Erste Sichtung

Zeig die ersten 30 Zeilen der .txt als Sanity-Check (deutsche Woerter? sinnvolle Saetze?). Bei offensichtlichen Whisper-Fehlern (englische Brocken im Deutschen, falsch erkannte Eigennamen) — flagge sie, gib Search-and-Replace-Vorschlag aus.

Gotchas

  • ffmpeg-Stand: Aktuell (Stand 2026-05-10) laeuft /opt/homebrew/bin/ffmpeg 8.1.1, keine afconvert-Workarounds mehr noetig. Falls’s wieder kaputt geht: afconvert -f WAVE -d LEI16@16000 -c 1 IN.MP4 /tmp/X.wav, dann transcribe.py auf der WAV statt mp4.
  • PyTorch-Patches in transcribe.py: Das Script patcht torch.serialization fuer PyTorch 2.6+ Kompatibilitaet (Lightning + pyannote rufen torch.load mit weights_only=False). Wenn whisperx upgegradet wird, pruefen ob der Patch noch noetig.
  • Eigennamen: “HeyJulia” wird oft als “Hey Julia” oder “Julian” erkannt; “Claude Code” → “Cloud Code”. Nach dem Lauf einmal mit Search-and-Replace durchgehen.
  • Filler-Words: WhisperX gibt “aehm”/“aeh” treu wieder. Beim Cut-Workflow spaeter entscheiden, nicht jetzt.
  • CUDA / MPS: transcribe.py nutzt device="cpu". MPS ist mit WhisperX nicht stabil (Stand 2026-05). CUDA: nicht relevant (Apple Silicon).

Output fuer Folge-Skills

Die .json ist die wichtigste Datei. Format pro Segment:

{
  "start": 12.34,
  "end": 18.92,
  "text": " Ich nutze Claude Code...",
  "words": [
    {"word": "Ich",   "start": 12.34, "end": 12.51, "score": 0.98},
    {"word": "nutze", "start": 12.52, "end": 12.74, "score": 0.97}
  ]
}

Konvertieren zu Remotion-Frames: frame = round(timestamp * fps). Bei 30 fps Composition: frame = round(12.34 * 30) = 370.

Status-Meldung am Ende

✓ Transkript fertig: youtube/transcripts/<name>.{txt,srt,json}
- Dauer: <X> Min
- Segmente: <N>
- Woerter: <M>
- Erste Erkennung: "<erste 80 Zeichen der .txt>"

Naechster Schritt: Lese-Cluster oder direkt Trim-Ranges?
  • scripts — wo transcribe.py lebt
  • MASTERPLAN — Phase 1 der VideoForge-Pipeline
  • Folge-Skill (TBD): vlog-cut-vorbereiten — Cluster-Vorschlag aus .json + leeres Trim-Sheet