Communitygithub.com

Video-Lokalisierung: Chinesisch-Synchro mit Stimmklon

Die englische Stimme eines Videos durch eine chinesische Synchronisation mit der geklonten Originalstimme ersetzen, auf identischer Zeitachse: gleiches Bild, gleiche Länge, Hintergrundmusik bleibt, zweisprachige Untertitel eingebrannt, mit Längen-, Kalt- und Hörprüfung.

Was ist Video-Lokalisierung: Chinesisch-Synchro mit Stimmklon?

Rezept Video-Lokalisierung, Schritt 3 (die Synchronisation), aus ChHsiching/video-dubbing-skill. Es liest das Rohvideo und einen zweisprachigen Untertitellauf und erzeugt eine zweite Version, ohne die erste anzutasten. Der Agent übersetzt für die Synchronisation — ganze Sätze nach Zeichenbudget pro Cue statt Untertitelfragmenten — und führt die Qualitätsprüfungen durch: Länge, Kaltprüfung, Hörprüfung und Kontrolle nach dem Einbrennen. Die `cook dub`-CLI erledigt den deterministischen Teil: Demucs bewahrt die Musik, IndexTTS2 klont die Stimme, jede Zeile wird per atempo in ihr Originalfenster gesetzt, ffmpeg brennt ZH+EN-Untertitel ein. Ergebnis: ein synchronisiertes MP4 exakt in Originallänge plus zh/en-SRTs.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ChHsiching/video-dubbing-skill/tree/HEAD/skills/video-dubbing

In Ihrer bevorzugten KI fragen

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

Dokumentation

Ersetze die englischen Originalvocals eines Videos mit chinesischem Voiceover auf einer identischen Zeitachse: das Video wird nie neu getaktet – jeder Frame behält seinen ursprünglichen Zeitstempel, und die synchronisierte Veröffentlichung hat exakt die Dauer des Rohvideos. Das synthetisierte Audio jedes Cues wird in sein eigenes ursprüngliches Fenster eingepasst (Cue-Start → Start des nächsten Cues) mit einem pro Cue angepassten Tempo; schnellere oder langsamere Synthese landen beide im Fenster. Das Ergebnis ist eine zweite Veröffentlichung – dasselbe Bild mit derselben Geschwindigkeit, chinesisches Audio, zweisprachige ZH+EN Untertitel eingebrannt.

Diese Fähigkeit übernimmt die beiden kreativen Teile, die das CLI nicht kann: Übersetzen für die Synchronisation (vollständige Sätze, geschrieben mit einem Zeichenbudget, nicht der Untertitelfragmentierung) und Durchführung der Qualitätssicherung (Längengate, Kaltprüfung, Hörprüfung, Prüfung nach dem Einbrennen). Die deterministische Ausführung (Demucs, IndexTTS2, Assembly, Neuskalierung, ffmpeg) wird vom Unterbefehl cook dub des cook CLI gehandhabt. Alle Stagenskripte leben im Cook-Paket (stages/dub/); jeder untenstehende Aufruf ist ein cook-Befehl. Einmaliges pip install -U video-cook aktualisiert alles.

Wann diese Fähigkeit eingesetzt wird

Du hast ein Video, das bereits Folgendes hat:

  • Eine Rohvideodatei (<output-root>/raw/<name>.raw.mp4) – das Original mit englischen Vocals.
  • Einen zweisprachigen Untertitellauf von video-subtitle – insbesondere transcript/<name>.en.full.srt (das vollständige englische Transkript in Sätzen, zusammengeführt aus whisperX-Fragmenten) und transcript/translations.txt.

Du möchtest eine chinesisch synchronisierte Veröffentlichung. Wenn du diese noch nicht hast, führe zuerst video-download und dann video-subtitle aus – diese Fähigkeit liest deren Ausgaben.

Was du produzierst

Drei Produkte werden ausgeliefert: cooked/<name>.dubbed.mp4 (rohes Video unverändert, chinesische Synchronisation, eingebrannte zweisprachige Untertitel – Dauer identisch mit dem Rohvideo), cloud-srt/zh.dub.srt + en.dub.srt (Upload-Untertitel). Alles andere sind Arbeitsdateien unter dubbed/ – der untenstehende kommentierte Baum zeigt jede einzelne.

Der Lauf ist erst abgeschlossen, wenn die Prüfungen von Schritt 6 bestanden sind.

Verzeichnisstruktur

Diese Fähigkeit fügt dubbed/ (Arbeitsverzeichnis) hinzu und schreibt die endgültigen Produkte nach cooked/ und cloud-srt/:

<output-root>/
├── raw/                            ← von video-download (diese Fähigkeit liest es)
│   └── <name>.raw.mp4
├── transcript/                     ← von video-subtitle (diese Fähigkeit liest + fügt hinzu)
│   ├── <name>.en.full.srt          ← vollständige englische Sätze (die Synchronisationsskriptquelle)
│   ├── translations_dub.txt        ← diese Fähigkeit schreibt: eine chinesische Zeile pro Cue
│   └── <name>.zh.dub.srt           ← diese Fähigkeit schreibt
├── cooked/                         ← endgültige Videos leben hier
│   ├── <name>.cooked.bar.mp4       ← von video-subtitle (unverändert)
│   └── <name>.dubbed.mp4           ← Produkt dieser Fähigkeit
├── cloud-srt/                      ← Upload-Untertitel leben hier
│   ├── zh.srt / en.srt             ← von video-subtitle (unverändert)
│   └── zh.dub.srt / en.dub.srt     ← Upload-Untertitel dieser Fähigkeit
└── dubbed/                         ← Arbeitsverzeichnis dieser Fähigkeit
    ├── _reference/
    │   └── ref.wav
    └── _full/
        ├── _segments/              ← pro-Cue IndexTTS2 Cache
        ├── dub.wav                 ← die Synchronisation auf der ursprünglichen Uhr
        ├── dubbing.srt             ← Arbeitsdatei (ZH, vor Kürzung)
        ├── dubbing.short.srt       ← Arbeitsdatei (ZH, Kürzungsausgabe)
        ├── dubbing.merged.srt      ← Arbeitsdatei (ZH, nach Kürzung; kopiert nach cloud-srt)
        ├── dubbing.en.srt          ← Arbeitsdatei (vollständige Sätze EN)
        ├── dubbing.en.short.srt / dubbing.en.merged.srt  ← ihre Kürzungs- und Zusammenführungsausgaben
        ├── dubbing.bilingual.srt   ← Arbeitsdatei (zweisprachige Vereinigung; die eingebrannt wird)
        ├── dubbing.cooked.ass     ← Arbeitsdatei (ass-Ausgabe, kopiert nach burn.ass)
        └── burn.ass                ← das tatsächlich eingebrannte ASS

Regel: dubbed/ ist das Arbeitsverzeichnis; cooked/<name>.dubbed.mp4 und cloud-srt/{zh,en}.dub.srt sind die Produkte. Niemals raw/, transcript/<name>.zh.srt, cooked/<name>.cooked.mp4 oder cloud-srt/{zh,en}.srt berühren – diese gehören zu video-subtitle. Wenn diese Fähigkeit auf halbem Weg fehlschlägt, ist die zweisprachige gekochte Lieferung immer noch vollständig.

Die Pipeline

Zwei Stufen nach der kreativen Arbeit: Synth dann Assemble, aufgerufen durch cook:

cook dub synth    <root> <name> --python <indextts-venv>/Scripts/python.exe
cook dub assemble <root> <name> --python <indextts-venv>/Scripts/python.exe [--keep-subs]
# oder beide:
cook dub full <root> <name> --python <indextts-venv>/Scripts/python.exe

Die folgenden Schritte beschreiben, was jede Stufe intern tut (damit du Ausgaben überprüfen und Fehler diagnostizieren kannst); die cook dub <stage>-Befehle sind, wie du sie ausführst.

Schritt 0 – Die Umgebungen auflösen

Es gibt zwei Python-Umgebungen, und sie zu verwechseln ist die Fehlerursache, die dieser Schritt verhindern soll:

  • Cooks Umgebung (System-Python oder ~/.venvs/video-tools/) – wo das cook-CLI lebt, mit whisperX/yt-dlp/torch für die Untertitel-Pipeline.
  • IndexTTS2s Umgebung (~/Git/index-tts/.venv) – eine separate venv, die indextts, torch, demucs und whisperx enthält (die Synchronisations-Pipeline fügt die letzten beiden zusätzlich zur Upstream-Sperrdatei hinzu). Diese Abhängigkeiten sind absichtlich schwer und isoliert; versuche nicht, sie in Cooks Umgebung zu installieren.

Cook führt jede Synchronisationsstufe als Unterprozess unter der IndexTTS2-venv über --python aus, sodass from indextts import ... dort aufgelöst wird. Jeder cook dub-Befehl in dieser Fähigkeit benötigt --python <indextts-venv>/Scripts/python.exe. Löse den venv-Pfad einmal auf (Standard ~/Git/index-tts/.venv) und verwende ihn für den gesamten Lauf wieder.

0a. Überprüfen, ob beide Umgebungen erreichbar sind:

<cook-venv>/Scripts/cook doctor                                    # whisperX/yt-dlp/ffmpeg
<indextts-venv>/Scripts/python -c "from indextts.infer_v2_5 import IndexTTS2; import demucs, whisperx; print('ok')"   # indextts (v2.5) + demucs + whisperx

0b. Einzelthread-Einschränkung. IndexTTS2 muss single-threaded laufen (OMP_NUM_THREADS=1), sonst produziert es Müll-Audio. Cook setzt dies intern, bevor es torch importiert, sodass du es nicht selbst exportieren musst.

Erledigt, wenn Cooks Arzt whisperX/yt-dlp/ffmpeg als installiert meldet, die IndexTTS2-venv indextts (v2.5) + demucs + whisperx importiert und du den absoluten Pfad zu <indextts-venv>/Scripts/python.exe kennst, um ihn als --python zu übergeben.

Schritt 1 – Vocals vom Rohvideo trennen

Das Originalaudio ist eine gemischte Spur (Vocals + BGM + SFX). Demucs trennt es, sodass wir eine saubere Referenz extrahieren und später auf BGM prüfen können.

cook dub separate <output-root> <name> [--model htdemucs] --python <indextts-venv>/Scripts/python.exe

Demucs lebt in der IndexTTS2-venv, also zeigt --python dorthin. Verwende htdemucs (einzelnes Modell, ~3GB RAM), nicht htdemucs_ft (Paket aus 4 Modellen, ~20GB RAM – OOM auf 32GB-Maschinen). Die Qualität ist etwas geringer, aber für die Referenzextraktion ausreichend.

Im Vordergrundmodus (Standard) verschiebt cook die getrennten Spuren automatisch nach dubbed/vocals.wav + dubbed/no_vocals.wav; im --detach-Modus verschiebst du sie selbst, nachdem der Erledigt-Marker erscheint.

Erledigt, wenn dubbed/vocals.wav UND dubbed/no_vocals.wav beide existieren mit einer Dauer, die dem Rohvideo ±0,5s entspricht.

Schritt 2 – Den Referenzclip extrahieren

IndexTTS2 benötigt einen 14-30 Sekunden langen, sauberen Clip des ursprünglichen Sprechers – es liest höchstens die ersten 15s, also ist ein vollständiges Fenster besser als ein kurzes. IndexTTS2 klont Prosodie, nicht nur Klangfarbe: Das Sprechtempo des Fensters wird zum Sprechtempo der gesamten Synchronisation. Der Standard-Auswähler nimmt die längste durchgehende Sprache, die dazu neigt, die langsamste, bedachteste Passage auszuwählen – oft falsch. Bevorzuge den Scanner:

cook dub scan-reference <output-root> <name> \
    [--full-band] [--python <indextts-venv>/Scripts/python.exe]

Er bewertet feste 15s-Fenster nach Silbenrate (dichte- und pausengefiltert) und schneidet die Top-3-Kandidaten (plus Full-Band-48k-Kopien mit --full-band). Dichte ist nur die halbe Geschichte – IndexTTS2 klont auch die Prosodie des Fensters, also bewerte Kandidaten auch nach Lebendigkeit: pyin F0 Std und Halbtonbereich pro Fenster (ein flaches Fenster synchronisiert flach; verwende librosa.pyin, NICHT detect_pitch_frequency, das Stimmhaftigkeit auf Stille meldet). Authentifiziere jede vererbte Referenzdatei vor der Wiederverwendung: Ein neu verarbeitetes Derivat behält seine Sprecherembeds und Tonhöhenstatistiken, verliert aber die Wellenformkorrelation, also bedeutet eine Korrelation nahe Null NICHT „anderen Sprecher“ – bewerte es gegen einen Ankerclip mit cook dub scan-reference --score <file> --anchor <anchor.wav> (echtes Audio desselben Sprechers landet nahe 0,94; synthetisierte Takes im Bereich 0,66–0,76 sind normal) und vergleiche pyin-Statistiken. So oder so: Das Ohr des Benutzers wählt die Referenz, immer – synthetisiere die Pilotensätze einmal pro Kandidat (Schritt 3a), überprüfe jeden Take mit einem ASR-Roundtrip eines kleinen Modells (fehlende Wörter signalisieren Kauderwelsch; traditionell-chinesische Ausgabe signalisiert einen Akzent, den das Fenster in den Take einfließen lässt), bewerte mit cook dub scan-reference --score, und übergib dann die lautstärkeangepassten wavs dem Benutzer.

Erledigt, wenn dubbed/_reference/ref.wav existiert, 14-30s lang ist und keine Stillelücke > 0,3s hat (ffmpeg -af silencedetect).

Schritt 3 – Für die Synchronisation übersetzen (der Agent macht dies)

Hier unterscheidet sich die Synchronisation von Untertiteln. Verwende nicht translations.txt (die Untertitelübersetzung) – sie folgt whisperX Fragmenten, die Sätze teilen. Synchronisation benötigt vollständige Sätze, damit das Chinesisch natürlich klingt, wenn es gesprochen wird.

Lese <output-root>/transcript/<name>.en.full.srt (das vollständige englische Transkript in Sätzen). Übersetze jeden Cue selbst und schreibe nach transcript/translations_dub.txt – eine chinesische Zeile pro englischem Cue, Zeile N = Cue N.

Die Zeichenbudget-Regel – der Kern der Synchronisationsübersetzung. Das Budget jedes Cues ist Fenstersekunden × normale Sprechrate, festgelegt bevor du schreibst: Das Fenster ist Cue-Start bis zum Start des nächsten Cues (Fenster + folgende Pause), die Rate wird gemessen, niemals angenommen – cook dub measure-rate auf dem vom Benutzer ausgewählten Piloten (Vorgehen: Schritt 3a). Eine angenommene Rate passiert jedes Gate und synchronisiert zu Sekunden toter Luft: Ein 45-minütiger Vortrag, budgetiert mit einer angenommenen 5,0 Zeichen/s gegenüber einer echten 6,93, hinterließ 83 Cues mit >2,5s Stille und kostete eine 82-Cue-Neusynthese. Schreibe innerhalb des Budgets: leicht darüber ist in Ordnung, deutlich darunter nicht – ein kurzer Take behält jetzt sein natürliches Tempo und hinterlässt eine Atempause, also bedeutet unterbudgetierter Text tote Luft und überbudgetierter Text hörbare Kompression. Kalibriere bei jeder Referenz- oder Dauerfaktoränderung neu: Ein Budget, das auf eine zurückgezogene Referenz kalibriert wurde, übersteht jedes Gate und synchronisiert dennoch zu toter Luft. Synthetisiere eine geschichtete Sonde (5-10 typische Cues pro Sprecher über Längenbereiche) und überprüfe das Skript erneut gegen die Fenster mit den gemessenen Raten – Vorgehen in REFERENCE.md → „Rate recalibration“. Wie man ein Budget legitim füllt (und was „Füllen“ nicht erfinden darf): REFERENCE.md → „Filling the char budget“.

Übersetzungsprinzipien (über das Budget hinaus):

  • Übersetze vollständige Gedanken, keine Fragmente. Das Englische ist bereits in vollständigen Sätzen; dein chinesischer Cue ist ein vollständiger Gedanke.
  • Behalte technische Begriffe auf Englisch, wo chinesische Entwickler dies tun – spec, plan, prototype, agent, token, skill, session, branch, route usw. Siehe REFERENCE.md → „Term retention list“.
  • Behalte Englisch für alles, was auf dem Bildschirm angezeigt wird – UI-Beschriftungen, Code, URLs, Dateinamen. Beispiele in REFERENCE.md → „Term retention list“.
  • Übersetze Konzepte, die standardmäßige chinesische Namen haben, wenn sie nicht auf dem Bildschirm angezeigt werden – die ausgearbeiteten Beispiele leben in der Begriffserhaltungsliste.
  • Die Zeilenanzahl muss der Cue-Anzahl entsprechen. Der erlaubte Weg, Anzahlen zu ändern, ist Schritt 3as build_merge.py, das beide Dateien zusammen umschreibt.

Erzeuge dann die SRT vor der Assembly (Zeitstempel von en.full.srt geerbt):

cook dub make-srt <output-root> <name>

Selbstüberprüfung – zwei Durchgänge, vor dem mechanischen Gate: Lese jede Zeile laut in Gedanken als gesprochenen Satz (klingt es wie etwas, das eine Person sagen würde?); überprüfe dann die folgende Begriffserhaltungsliste gegen jede Zeile (alles auf dem Bildschirm bleibt Englisch, Standardkonzepte gehen auf Chinesisch). Dies überprüfst du deine eigene Arbeit; die Unteragentenüberprüfung unten ist die Kaltprüfung.

Längengate – mechanisch (reine Arithmetik, dauert eine Sekunde):

cook dub gate <output-root> <name> --rate <measured chars/s>

Es überprüft jede Zeile auf drei Arten gegen ihr Cue-Fenster: kurze Zeilen (≤8 Silben – IndexTTS2s Erzähltempo-Falle, schreibe voller um oder lasse Schritt 3a zusammenführen), Budgetfehler (geschätzte Sprache weit über ihrem Fenster – Text muss gekürzt werden – oder weit darunter – das Fenster bekommt tote Luft, fülle es), und die Abdeckung insgesamt (Σ geschätzte Sprache / Σ Fenster – eine gleichmäßig dünne Übersetzung besteht jede Zeilenprüfung und synchronisiert dennoch zu langen Stille; gesund 90-105%). --rate ist erforderlich (der gemessene Wert; --self-measure leitet es von vorhandenen Takes ab). Exit 1 listet die Zeilen und das Abdeckungsurteil auf; schreibe um und führe erneut aus, bis es besteht. Ein überbudgetierter Cue wird durch kürzeres Umschreiben oder Zusammenführen mit seinem Nachbarn mit cook dub merge behoben – niemals, indem man ihn einer Tempo-Kompression überlässt.

Qualitätssicherung – Fan-Out-Unteragentenüberprüfung (obligatorisch, vor der Synthese). Die Hörprüfung und diese Überprüfung sind die einzigen Tore vor Stunden der Synthese. Verteile einen Unteragenten mit Lesezugriff sowohl auf <name>.en.full.srt als auch translations_dub.txt und bitte ihn, für jeden Cue zu prüfen:

  1. Übersetzungsgenauigkeit – übermittelt das Chinesische das Englische treu? Keine weggelassenen Klauseln, kein hinzugefügter Inhalt (nichts, was das Englische nicht sagt), keine Fehlübersetzungen.
  2. Rechtschreibung von Eigennamen – Namen (Personen, Produkte, Unternehmen) genau wie von der Quelle verwendet. „Claude“ nicht „克劳德“, „IndexTTS“ nicht „索引TTS“, es sei denn, ein standardmäßiger chinesischer Name existiert tatsächlich.
  3. TTS-Lesbarkeit – wird IndexTTS2 dies natürlich aussprechen? Keine unangenehmen Zeichenfolgen, keine verwaisten Präfixe.

… [gekürzt für die Übersetzung]

Verwandte Skills