Communitygithub.com

ThomasHMD/subtitles

Repariert einen Premiere-Pro-Untertitel-/Transkript-JSON-Export (eine voller Tippfehler steckende automatische Transkription, insbesondere bei Eigennamen) durch erneutes lokales Transkribieren des Videos mit whisper.cpp und Neuerstellung eines JSON im exakten Premiere-Format (direkt wieder importierbar) mit korrigierten Namen anhand eines Referenzskripts, wiederhergestellter Interpunktion und Großschreibung, in Anführungszeichen gesetzten Werkstiteln und auf das Audio ausgerichteten Wortzeitangaben durch Forced Alignment.

Was ist subtitles?

Diese Fähigkeit behebt häufige Probleme mit automatisch generierten Transkripten aus Adobe Premiere Pro. Diese Transkripte enthalten oft Tippfehler, insbesondere bei Eigennamen wie Fotografen- oder Künstlernamen. Der Skill transkribiert das Originalvideo lokal mit whisper.cpp, um eine genauere Textbasis zu erhalten. Anschließend wird eine JSON-Datei im exakten Premiere-Format erstellt, die direkt wieder importiert werden kann. Dabei werden Namen mithilfe eines Referenzskripts korrigiert, Satzzeichen und Großschreibung wiederhergestellt, Werkstitel in Anführungszeichen gesetzt und die Wortzeitangaben durch Forced Alignment präzise auf die Audiospur ausgerichtet. Der Skill unterstützt die Sprachen Französisch und Englisch und erfordert die Einrichtung von whisper-cli, ffmpeg und einem Whisper-Modell. Er ist für den Einsatz mit Claude Code, Cursor, Codex und ähnlichen KI-Agenten konzipiert und bietet einen detaillierten Workflow zur Fehlererkennung und Korrektur.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ThomasHMD/premiere-rough-cut/tree/HEAD/skills/subtitles

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

subtitles: Premiere-Pro-Untertitel reparieren

Einmalige Einrichtung: siehe INSTALL.md im Kit-Stammverzeichnis. Mit dem Plugin lautet die Einrichtungszeile bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}"; bei einer manuellen Installation (die vier skills/-Ordner nebeneinander nach ~/.claude/skills/ kopiert) führen Sie bash install.sh aus dem Kit-Stammverzeichnis aus. Skripte befinden sich im scripts/-Ordner dieser Fähigkeit. Diese Fähigkeit verweist auf die andere als ../rough-cut/....

Was die Fähigkeit tut

Premiere erzeugt ein automatisches Transkript (ein .json-Export), das oft voller Tippfehler ist, vor allem bei Eigennamen (der Name eines Fotografen wird in zwei nicht zusammenhängende Wörter umgewandelt). whisper.cpp transkribiert viel besser. Diese Fähigkeit transkribiert das Video erneut lokal und erstellt dann ein .json im exakten Premiere-Format (direkt wieder importierbar): Namen werden mit Hilfe eines Referenzskripts korrigiert, Satzzeichen und Großschreibung wiederhergestellt, Werkstitel in Anführungszeichen gesetzt. Schließlich werden die Zeitangaben durch Forced Alignment auf das Audio ausgerichtet (whispers Zeitstempel driften).

  • JA: lokale Transkription, Namenskorrektur, Satzzeichen und Groß-/Kleinschreibung, Anführungszeichen um Titel, Zeitangaben-Ausrichtung auf das Audio (Forced Alignment), ein Format identisch mit Premiere, bereit zum erneuten Import.
  • NEIN: Schneiden oder Grobschnitt des Videos (das ist rough-cut), Übersetzen, Neusynchronisieren einer bereits korrekten Untertiteldatei, .srt/.vtt-Untertitel (das Format hier ist Premiere-eigenes JSON).

Erwartete Eingaben

  1. Das exportierte Video aus Premiere (.mp4/.mov): es enthält das zu transkribierende Audio.
  2. Das Untertitel-.json aus Premiere exportiert: es gibt das Zielformat (Schlüssel, speaker-UUID, Sprache) zum Klonen vor.
  3. Das Referenzskript des Videos, in jeder lesbaren Form (Klartext, Markdown, ein Google Doc, eine Notion-Seite, ein eingefügter Text): die Autorität für die Schreibweise von Eigennamen (Personen, Werke, Orte, Marken). Wenn es keins gibt, fragen Sie danach, oder korrigieren Sie nur die offensichtlichen Tippfehler und behalten Sie whispers Schreibweise für unsichere Namen bei.

Sprache

Typografie (Abstände um Satzzeichen), akzentuierte Buchstaben, Zeichensätze, Anführungszeichen und Rechtschreibnormalisierungen leben in languages/<code>.json (fr und en sind eingebaut), niemals im Code. Die Sprache wird durch --lang <code> ausgewählt, falls nicht, durch die Sprache des Premiere-JSON, falls nicht, durch die im whisper-Transkript aufgezeichnete Sprache, sonst en. Wie die Dateien funktionieren und wie man eine Sprache hinzufügt: ../rough-cut/references/languages.md (gleicher Mechanismus; diese Fähigkeit hat ihren eigenen languages/-Ordner).

Anforderungen (einmal pro Maschine)

whisper-cli + ffmpeg + das Modell ~/Models/whisper/ggml-large-v3-turbo.bin. Siehe ../rough-cut/references/whisper-setup.md (gemeinsame Einrichtung). Überprüfen: which whisper-cli ffmpeg && ls ~/Models/whisper/.

Forced Alignment (Ausrichtung der Zeitangaben auf das Audio, Schritt 6b):

pip3 install --break-system-packages ctc-forced-aligner torch torchaudio unidecode

Ein ONNX-Modell von etwa 1,2 GB wird beim ersten Start heruntergeladen (Cache ~/ctc_forced_aligner/). Überprüfen: python3 -c "import ctc_forced_aligner".


Arbeitsablauf

Die scripts/...-Befehle unten gehen davon aus, dass Sie im Fähigkeitsordner sind. Das Arbeitsverzeichnis kann zwischen zwei Shell-Aufrufen zurückgesetzt werden: entweder cd einmal in den Fähigkeitsordner oder jedes Skript mit seinem absoluten Pfad versehen. Arbeitsdateien (Audio, Transkript, Korrekturen) kommen in einen temporären Ordner außerhalb jedes synchronisierten Ordners.

1. Das Video und das Eingabeformat analysieren

Zuerst: das Original sichern. Premiere kann das eingegebene .json bei einem erneuten Export ÜBERSCHREIBEN, und es ist die einzige Wahrheit zur Überprüfung der Zeitangaben in Schritt 7:

cp "<Reel.json>" /tmp/subs_original_premiere.json
ffprobe -v error -show_entries format=duration:stream=codec_type,r_frame_rate \
  -of default=noprint_wrappers=1 "<video>"

Notieren Sie die Dauer (das letzte Wort muss hineinfallen) und die fps. Überprüfen Sie dann das eingegebene Premiere-JSON, um das Format zu bestätigen:

python3 scripts/inspect_format.py "<Reel.json>"

Es gibt die Schlüssel (oben/Segment/Wort), die speaker-UUID, die Sprache, die Anzahl der Segmente und den aktuellen Text Segment für Segment (= die Liste der zu korrigierenden Tippfehler) aus. Das erwartete Format ist in references/premiere-format.md dokumentiert: lesen Sie es, wenn die Inspektion ungewöhnliche Schlüssel zeigt.

2. Lokal transkribieren (whisper.cpp)

python3 scripts/extract_audio.py "<video>" /tmp/subs_audio.wav
python3 scripts/transcribe.py /tmp/subs_audio.wav /tmp/subs_transcript.json --model large-v3-turbo --language <code>

Etwa 8 s für 3 Min auf Apple Silicon. Das Transkript hat Segmente mit text (mit Satzzeichen, Groß-/Kleinschreibung) und zeitgestempelten words.

2b. Wenn whisper NICHT interpunktiert hat (kontinuierliche Lieferung): erneut interpunktieren

Bei schnellen Monologen gibt whisper manchmal einen Strom ohne Satzzeichen und ohne Großbuchstaben zurück (Segmente brechen mitten im Satz ab, kein ./,). Klarer Hinweis: build_subs.py meldet eos: 0. Ohne Satzzeichen sind die Untertitel unlesbar. Kurze Überprüfung: python3 scripts/words_of.py /tmp/subs_transcript.json 0 1 2 --plain.

Wenn ja, interpunktieren Sie selbst (es ist eine LLM-Aufgabe, nicht whispers): schreiben Sie den text jedes Segments mit Satzzeichen und Satzanfängen in Großbuchstaben neu, behalten Sie whispers Wörter wörtlich bei: fügen Sie NUR Satzzeichen und Groß-/Kleinschreibung hinzu; lexikalische Korrekturen (Namen, Akronyme) bleiben in corrections.json. Satzzeichen IMMER am Wort befestigt (so?, nicht so ?): ein durch ein Leerzeichen abgetrenntes Zeichen wird zu einem isolierten Token, das die Ausrichtung still fallen lässt (114 ?/! gingen einmal auf einmal verloren). build_subs.py setzt die sprachspezifischen Abstände (für Französisch ein geschütztes Leerzeichen) selbst zurück. Speichern Sie das Ergebnis in einem JSON {index: "interpunktierter text"}, dann:

python3 scripts/repunctuate.py --transcript /tmp/subs_transcript.json --punct /tmp/punct.json --output /tmp/subs_transcript_punct.json

Das Skript lehnt ab, wenn Sie ein Wort hinzugefügt, entfernt oder geändert haben (es zeigt den Unterschied): das hält die Wort-zu-Zeitangaben-Ausrichtung intakt. Achten Sie auf den Fluss über Segmente hinweg: Ein Segment, das einen Satz fortsetzt, beginnt klein, eines, das einen Satz eröffnet, beginnt mit einem Großbuchstaben. Verwenden Sie dieses interpunktierte Transkript für den Rest (--transcript in Schritt 6).

Löschen Sie auch jede Halluzination am Ende des Clips: In der finalen Stille erfindet whisper oft eine Zeile wie einen Untertitel-Credit oder "Vielen Dank fürs Zuschauen" (die typischen Zeilen jeder Sprache sind unter whisper_hallucinations in languages/<code>.json aufgelistet). Löschen Sie es mit einer seq_rule N auf 0. Eine weitere Halluzination: aufeinanderfolgende Segmente mit identischem Text, deren Wörter eine nahezu Null-Dauer haben (start==end), über eine Stille erfundene Wiederholungen ("hier gehen wir" x3). Erkennung: Segmente i und i+1 mit identischem Text und Wörtern der Dauer 0. Behebung: Löschen Sie sie aus dem Transkript vor dem Bau (del segs[i:j]).

3. Das whisper-Transkript und das Referenzskript lesen

Drucken Sie das Transkript Segment für Segment (text) und vergleichen Sie es mit dem eingegebenen Premiere-Text (Schritt 1). whisper korrigiert bereits viel, behält aber Tippfehler bei Namen. Lesen Sie das Referenzskript, um die kanonische Schreibweise von Eigennamen und der darin zitierten Werkstitel zu erhalten.

4. corrections.json erstellen (der intelligente Kern)

Hier wird die Qualität entschieden. Erstellen Sie eine Korrekturendatei, indem Sie das, was whisper gehört hat, mit den Namen des Skripts vergleichen. Untersuchen Sie die wortweise Aufteilung der betroffenen Segmente, um genaue Regeln zu schreiben:

python3 scripts/words_of.py /tmp/subs_transcript.json 2 9 38   # indizierte Token der zu untersuchenden Segmente

Die Ausgabe indiziert jedes Wort (9:Smyth 10:Jones): das ermöglicht es Ihnen, genaue Regeln zu schreiben, ohne die Tokenisierung erraten zu müssen (wie viele Token ein Name einnimmt, Bindestriche beibehalten usw.).

Format von corrections.json (alle Schlüssel optional):

{
  "quote_char": "\"",
  "normalize_cotes": true,
  "seq_rules": [
    [["jon","smyth"], ["John","Smith"]],
    [["train","park"],    ["Trent","Parke"]],
    [["arthus","bertrand"], ["Arthus-Bertrand"]]
  ],
  "word_rules": {"macdum": "Magnum", "scholler": "Schoeller"},
  "titles": [
    {"match": ["the","decisive","moment"], "canonical": ["The","Decisive","Moment"]},
    {"match": ["errance"], "canonical": ["Errance"], "sep_comma": true}
  ]
}
  • seq_rules: Mehrwortnamen oder 1 zu N / N zu 1. Der Abgleich erfolgt auf den Wörtern in Kleinbuchstaben, ohne Satzzeichen. Verwenden Sie es für jeden Namen, der 2 oder mehr whisper-Wörter umfasst, oder wenn sich die Anzahl der Wörter ändert. Groß-/Kleinschreibung: die Zielwörter werden WÖRTLICH verwendet: Schreiben Sie die endgültige Groß-/Kleinschreibung, die Sie wünschen, einschließlich der Position im Satz (["Heute","sind",...], wenn das Wort den Satz eröffnet, nicht ["heute",...]). Gleiche Länge Quelle/Ziel: Satzzeichen (interne Kommas) und Zeitangaben werden indexbasiert beibehalten; unterschiedliche Längen: Zeitangaben werden neu verteilt und nur die Satzzeichen des ersten/letzten Wortes überleben (die internen Kommas ersetzter Wörter gehen verloren: lesen Sie diese Segmente in Schritt 7 erneut). Löschen: Ein leeres Ziel [["uh"], []] entfernt das Wort (heben Sie es sich für echte isolierte Geräusche auf, die whisper verdoppelt hat; korrigieren Sie ein schlecht transkribiertes Wort, anstatt es zu löschen, sonst verlieren Sie einen Teil eines Satzes).
  • word_rules: Ein Einwortname, Groß-/Kleinschreibung erzwungen (Kleinschlüssel zu exaktem Wert).
  • titles: Zitierte Werke (Bücher, Serien, betitelte Fotografien) erhalten automatische Anführungszeichen (öffnend beim ersten Wort, schließend beim letzten) plus einen canonical für die korrekte Groß-/Kleinschreibung des Titels. sep_comma: true fügt ein Komma nach dem Titel hinzu (nützlich, wenn mehrere Titel aufeinander folgen). Setzen Sie Werke in Anführungszeichen, nicht Personennamen oder Marken.
  • normalize_cotes: Wendet die Rechtschreibnormalisierungen der Sprachdatei an (normalize_words), für Varianten, die whisper inkonsistent schreibt. Aus, es sei denn, Sie setzen es.
  • french_typography: Der Schalter für die typografischen Abstände der Sprache (der Name ist historisch; er gilt für jede verwendete Sprache). Standard aus der Sprachdatei: für Französisch ein geschütztes Leerzeichen (U+00A0) vor den doppelten Satzzeichen und dem schließenden Anführungszeichen und nach dem öffnenden Anführungszeichen; für Englisch keins. Setzen Sie es nur auf false, wenn Sie befestigte Satzzeichen wünschen. Wenn Sie in Schritt 2b erneut interpunktieren, MÜSSEN die Satzzeichen befestigt sein (Flop:); build_subs.py setzt die Abstände selbst zurück.

5. Unsicherheiten MIT dem Benutzer klären (niemals erfinden)

whisper produziert manchmal ein mehrdeutiges oder unverständliches Nicht-Name-Wort. Raten Sie nicht stillschweigend. Listen Sie diese Punkte mit ihrem Zeitcode auf und fragen Sie den Benutzer, was wirklich gesagt wird, und bieten Sie eine Hypothese an, wenn der Kontext oder das Skript eine nahelegt. Unterscheiden Sie:

  • Direkt korrigieren: Eigennamen, die durch das Skript bestätigt wurden; offensichtliche und sichere Tippfehler.
  • Zuerst fragen: Mehrdeutige Nicht-Name-Wörter oder jede Korrektur, die die Bedeutung ändert (z. B. whisper "wer fühlt" gegen das Skript "ohne": eine Bedeutungs-Umkehrung, melden Sie es, auch wenn das Skript es klärt).

Schreiben Sie den gesprochenen Stil (Slang, Füllphrasen, Wiederholungen) nicht um: Untertitel müssen dem Audio folgen.

Was in die Datei schreiben, während Sie auf die Antwort warten (Sie müssen die Generierung nicht blockieren): Erstellen Sie eine erste Version, die alle sicheren Korrekturen plus Ihre beste Hypothese für die häufigen mehrdeutigen Wörter anwendet (und melden Sie sie), aber behalten Sie whispers rohe Schreibweise für einen unsicheren NAMEN bei, der nicht im Skript vorkommt: Erfinden Sie niemals einen Eigennamen. Liefern Sie diese Version mit der Liste der zu validierenden Punkte (Zeitcodes) und generieren Sie dann neu nach der Antwort, indem Sie corrections.json aktualisieren. Das ist der normale Ablauf: generieren, mit den Fragen präsentieren, verfeinern.

6. Die korrigierte Datei erstellen

python3 scripts/build_subs.py \
  --transcript /tmp/subs_transcript.json \
  --original "<Reel.json>" \
  --corrections /tmp/corrections.json \
  --output "<folder>/<name>_corrige.json" [--lang <code>]

Das Skript klont das Format des Originals (sprecher-UUID, Sprache, sortierte Schlüssel, minimiertes UTF-8), setzt Satzzeichen und Groß-/Kleinschreibung zurück, wendet die Korrekturen an, fügt die Anführungszeichen hinzu, berechnet eos neu und gibt einen Validierungsbericht aus.

Schreiben Sie <name>_corrige.json NEBEN das Original, überschreiben Sie niemals den Original-Export (es ist die Quelle des Benutzers). Das Suffix _corrige ist ein Dateiname, auf den sich die Skripte verlassen: behalten Sie es.

6a. Die 2 wiederkehrenden Fallen von build_subs.py überprüfen (jedes Mal)

Zwei in vielen Videos gesehene Fehler, die nach JEDEM Build zu überprüfen sind:

  1. Dezimalzahlen verdoppelt. whisper teilt 6.6 in 2 Token auf (6 + .6; ebenso 1,33 oder 4 AM in 4 + AM); die Wiedereinfügung von Satzzeichen verdoppelt sie in der Ausgabe (1.4 .4, 6.6. .6), und seq_rules passen schlecht (die Normalisierung entfernt kein internes ./,). Erkennung: Grep in der endgültigen Ausgabe nach den Mustern \d[.,]?\s+[.,]\d. Behebung: Operation am Transkript VOR dem Build: führen Sie die 2 Token zu einem zusammen ({'text':'1.4','start':a.start,'end':b.end,...}; whisper-Wort-Schema = text/start/end/confidence, NICHT duration), dann neu bauen.
  2. Isoliertes Satzende-Satzzeichen weggefallen. Ein ?/!/: im text des whisper-Segments, aber ohne eigenes Wort-Token, verschwindet (How did we do it ? verliert sein ?). Erkennung: Vergleichen Sie count('?') (und !, :) zwischen dem whisper-Text und der Ausgabe. Behebung: Bearbeiten Sie das Ausgabe-JSON nachträglich: hängen Sie ? (mit dem sprachspezifischen Abstand) an das vorherige Token an.

Wenn Falle 1 erkannt wird, korrigieren Sie das Transkript und bauen Sie neu (Schritt 6). Wenn Falle 2, patchen Sie die Ausgabe direkt.

6b. Die Zeitangaben auf das Audio ausrichten: Forced Alignment (IMMER)

whispers Wortzeitangaben DRIFTEN (gemessen bis zu 7 s zu früh, nichtlinear) bei schnellen, mehrfach aufgenommenen Monologen: whisper quetscht die Stille zwischen den Aufnahmen zusammen, sodass die Stimme NACH dem Untertitel ankommt. Typische Beschwerde: "Wenn das 'Ah' erscheint, höre ich schon den nächsten Satz". DTW (-dtw) ändert nichts (gleiche Offsets), und eine Zeitverzerrung auf spärlichen Ankern verzerrt die bereits richtigen Zonen. Der whisper-Text ist gut, nur seine Zeitangaben sind falsch. Forced Alignment korrigiert das:

python3 scripts/align.py --transcript /tmp/subs_transcript.json --audio /tmp/subs_audio.wav --output /tmp/transcript_aligned.json

Überprüfen Sie das Ergebnis, indem Sie mindestens ein Segment in der Mitte und eines am Ende mit dem Original vergleichen (start/end des Segments gegenüber /tmp/subs_original_premiere.json). Das alignierte Transkript sollte näher an den tatsächlichen Audio-Offsets sein. Wenn es noch driften sollte, führen Sie align.py erneut mit einem anderen Modell aus (--model <name>).


Referenzen

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Verwandte Skills