Communitygithub.com

Perso Lip-Sync-Dub — Mehrsprachen-Voice-Swap

Perso-AI-Mehrsprachen-Lip-Sync-Dubbing für Claude/Cursor/Codex: Upload→Split→Übersetzen→Merge→MP4. README mit Demo-GIFs — Mund zum Dub-Track.

Was ist Perso Lip-Sync-Dub — Mehrsprachen-Voice-Swap?

Video Localization Schritt 2 (Dub-Polish): perso-dubbing-plugin-dubbing. Übersetztes SRT/Video → Lip-Sync-Mehrsprachen-Dub-MP4 vor bilingualem Hardburn.

Funktioniert mit✓Claude Code✓Codex CLI✓Cursor✓Antigravity✓Gemini CLI
npx skills add https://github.com/perso-ai/perso-dubbing-plugin/tree/main/skills/dubbing

In Ihrer bevorzugten KI fragen

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

Dokumentation

/dubbing

Eine Fähigkeit, die Videos automatisch über die Perso AI Dubbing API synchronisiert.

Kernregeln (müssen befolgt werden)

  • Nur der Worker sieht den rohen Schlüssel. Öffnen Sie den Schlüssel niemals mit Read, geben Sie ihn aus oder übergeben Sie ihn als Befehlszeilenargument. Worker senden ihn nur im XP-API-KEY-Header.
  • Ein Befehl = der gesamte Auftrag. scripts/dubbing.mjs erledigt Hochladen · Teilen · Übersetzen · Zusammenführen · Speichern selbstständig. Führen Sie prepare_input.mjs oder probe_split.mjs niemals davor aus – es sind Debug-Werkzeuge, und probe_split.mjs führt einen echten Upload durch (das Video würde zweimal hochgeladen werden).
  • Führen Sie dubbing.mjs immer im Hintergrund aus. Aufträge dauern Minuten bis Stunden; ein Timeout der Vordergrund-Shell bricht die Ausführung mittendrin ab.
  • Sprachen nicht angegeben → Quelle auto, Ziel en.
  • Mehrere Sprachen in einem Befehl (--target en,zh,ja) – Hochladen/Teilen erfolgt einmal und wird pro Sprache wiederverwendet. Niemals einmal pro Sprache ausführen (lädt die Quelle jedes Mal neu hoch).
  • Fortschritt zuverlässig weiterleiten. Geben Sie die [progress]-Zeilen der stdout des Workers wörtlich oder zusammengefasst im Chat wieder – und kündigen Sie keine Schritte an, die nicht erschienen sind (Teilen/Zusammenführen gibt es nur für Videos, die das Limit überschreiten). Die eingerückten Detail-Logs auf stderr müssen nicht weitergeleitet werden.
  • Halten Sie den Benutzer während der Ausführung auf dem Laufenden. Synchronisation, Lippenbewegungen und Audiotrennung drucken alle einen [status]-Herzschlag (Phase + Elementanzahl, z.B. ja 4/6 · en 1/6 oder separating — file 2/5, mit einem Hinweis next check ~Nm), und jedes fertige Element wird als [progress]-Zeile gestreamt. Überprüfen Sie die Hintergrundausgabe etwa 3 Minuten nach dem Start, dann im angegebenen Intervall (10 min für Medien ≤10 min, 30 min für längere): Leiten Sie jede neue [progress]-Zeile sofort weiter, ansonsten posten Sie die neueste [status]-Zeile als einzeiliges Update. Erfinden Sie niemals Prozentsätze, verstrichene Zeit oder ETAs – geben Sie nur das weiter, was die Zeilen sagen. Stopps, die den Benutzer benötigen ([space-select], [split-confirm], [free-limit], [resume-check], [credit-check], Credit-Ende, Fertigstellung) beenden den Prozess, sodass sie ohne Polling sichtbar werden.
  • Benennen Sie Ihre Laufzeit für Telemetrie (still). Fügen Sie --host <claude-code|codex|cursor|antigravity|gemini> zum Worker-Befehl hinzu und nennen Sie den Agenten, als den Sie ausgeführt werden, wenn Sie es erkennen können. Es taggt nur Nutzungstelemetrie – zeigen Sie es dem Benutzer niemals an und fragen Sie ihn niemals danach. Lassen Sie es weg, wenn Sie unsicher sind.
  • Nicht unterstützte Formate werden automatisch übersprungen und der Rest wird weiterverarbeitet – geben Sie den Überspring-Hinweis weiter.
  • Eine Pause ist kein Fehler. Eine [space-select], [split-confirm], [free-limit], [credit-check] oder [resume-check]-Zeile bedeutet, dass die Ausführung gestoppt wurde, um Sie etwas zu fragen – sie beendet sich mit 0 (sieht also nie wie ein Fehler aus), aber der Auftrag ist nicht abgeschlossen. Wenn eine dieser Zeilen vorhanden ist, melden Sie die Ausführung niemals als erledigt: Leiten Sie sie weiter und handeln Sie danach. Die Zeilen sind das Signal, nicht der Exit-Code.

Einrichtung (träge – kein vorheriger Schritt)

  1. API-Schlüssel – kein Schritt, den Sie zuerst ausführen. Der Worker sperrt sich selbst, sobald ein Befehl ausgeführt wird, der die Perso-API benötigt: Beim ersten solchen Lauf öffnet er eine Browserseite (Anmelden, ein Klick – der Schlüssel wird verschlüsselt gespeichert) oder druckt dateibasierte Anweisungen, wenn kein Browser geöffnet werden kann – leiten Sie sie an den Benutzer weiter. Auf einem kopflosen/SSH-Rechner überspringt der Worker den Browser-Flow vollständig und beginnt mit der Datei/--import-Registrierung (die Browserseite kann nur einen Schlüssel an den Rechner liefern, auf dem sie läuft) – leiten Sie diese Anweisungen auf die gleiche Weise weiter. Lösen Sie die Schlüsselregistrierung niemals selbst aus: Der Worker startet bei Bedarf connect.mjs/resolve_key.mjs --watch, führen Sie diese also nicht aus, und führen Sie auch nicht resolve_key.mjs --check als vorherigen Schritt aus (nur, wenn der Benutzer explizit fragt, ob ein Schlüssel registriert ist – ein fehlender Schlüssel ist kein Fehler). Fügen Sie den Schlüssel niemals in den Chat ein. Holen Sie sich einen Schlüssel: https://developers.perso.ai/api-keys
  2. ffmpeg/ffprobe – wird nur automatisch installiert, wenn ein Video das Planlimit überschreitet und geteilt werden muss (genehmigen Sie, wenn um Erlaubnis gebeten wird). Manuelle Überprüfung: node scripts/check_deps.mjs.

Ausführung

Sammeln Sie die Eingabe (lokaler Pfad oder URL – fragen Sie erneut, wenn sie fehlt) und führen Sie im Hintergrund aus – der Worker führt die Schlüsselsperre bei erstem Bedarf selbst durch; leiten Sie einfach seine gedruckten Anweisungen weiter, wenn die Registrierung startet:

  • Einzeln: node scripts/dubbing.mjs "<datei|URL>" [--source auto] [--target en] [--space "space name"] [--out result.mp4] [--lipsync] [--no-save]
  • Mehrsprachig / Mehreingabe (eine oder mehrere Eingaben; URLs und Dateien können gemischt werden): node scripts/dubbing.mjs "<URL>" "<datei>" --target en,ja – eine Ausgabe pro Eingabe × Sprache, neben jeder Quelle gespeichert (--out <ordner> sammelt sie).
  • Ordner (Stapel): node scripts/dubbing.mjs "<ordner>" [--target en,zh] [--recursive] [--out ausgabe-ordner]

Sprachcodes – --target akzeptiert einen Sprachcode (en, ja) oder ein regionales Tag. Regionale Varianten gibt es nur für Englisch (en = US-Standard, en-GB = UK), Portugiesisch (pt = Brasilien-Standard, pt-PT = Portugal) und Spanisch (es = Mexiko-Standard, es-ES = Spanien); en-US, pt-BR und es-MX sind akzeptierte Schreibweisen dieser Standards. Jede andere Sprache hat eine einzelne Variante, und --source benötigt nur die Sprache (ein regionales Tag wird dort als reine Sprache behandelt).

  • Region im Request genannt → verwenden Sie genau dieses Tag. Eine Region ohne Variante (z.B. australisches Englisch) → sagen Sie dem Benutzer, dass nur die aufgeführten Optionen existieren, und lassen Sie ihn vor der Ausführung wählen.
  • Zwei-Buchstaben-Tokens sind Sprachcodes, keine Länder: uk ist Ukrainisch – britisches Englisch ist en-GB. Gleiche Falle für ca (Katalanisch), be (Belarussisch), eu (Baskisch). Wenn die Formulierung des Benutzers beides bedeuten könnte, fragen Sie vor der Ausführung, was gemeint ist.
  • Sprache ohne Region genannt → die Standardvariante. Nennen Sie für diese drei Sprachen die angewandte Standardvariante im Lieferhinweis (z.B. „Spanisch (Mexiko) – verwenden Sie es-ES für Spanien").

Speicherort – --out akzeptiert entweder einen Ordner (ein vorhandenes Verzeichnis oder einen Pfad, der auf / endet), der die Ergebnisse darin sammelt, oder einen Dateipfad für eine einzelne Eingabe (die tatsächliche Erweiterung wird angehängt, wenn der Pfad keine hat). Standardmäßig neben jeder Quelldatei; fragen Sie nicht. Geben Sie es beim ersten Auftrag der Sitzung in der Startzeile an (z.B. „Ergebnisse werden neben den Originalen gespeichert – sagen Sie mir jetzt, wenn Sie einen anderen Ordner wünschen") und starten Sie sofort, ohne auf eine Antwort zu warten. Wenn der Benutzer einen Ordner nennt – mit dieser Anfrage oder später in dieser Sitzung – führen Sie mit --out "<ordner>" aus und verwenden Sie diesen Ordner für jeden späteren Auftrag, bis er geändert wird. Wenn er nach einem bereits gestarteten Lauf umleitet, verschieben Sie die fertigen Dateien dorthin, wenn der Lauf abgeschlossen ist. Ausnahme: Wenn jede Eingabe eine URL ist (kein lokaler Quellordner), fragen Sie vor dem Start, wo gespeichert werden soll.

Auswahl des Arbeitsbereichs – Bei mehreren Arbeitsbereichen stoppt der Worker vor dem Hochladen, druckt [space-select]-Zeilen (Name | (Plan) | verbleibende Credits) und stoppt. Zeigen Sie dem Benutzer NUR diese Optionen (keine internen Nummern), fragen Sie, welche, und führen Sie erneut mit --space "<space name>" aus. Ein Arbeitsbereich → keine Frage; PERSO_SPACE_SEQ fixiert ihn.

Bestätigung des Teilens – Wenn die Eingabe das Längen- oder Größenlimit überschreitet und automatisch geteilt & zusammengeführt werden muss (Synchronisation, Synchronisation+Lippenbewegungen oder Audiotrennung), stoppt der Worker und druckt [split-confirm]-Zeilen. Leiten Sie sie weiter und fragen Sie den Benutzer: Es überschreitet das Längen-/Größenlimit, daher ist automatisches Teilen → Verarbeiten → Zusammenführen erforderlich, was weniger ausgefeilt sein kann, als wenn sie es selbst aufteilen – automatisch fortfahren? Bei Zustimmung führen Sie den gleichen Befehl mit --allow-split erneut aus (bis zu diesem Zeitpunkt wird nichts berechnet, also ist ein erneuter Durchlauf kostenlos). Stapelläufe: --allow-split autorisiert jedes Teilen im Lauf.

Nicht speichern (nur Server) – Wenn der Benutzer das Video synchronisiert haben möchte, aber nicht als lokale Datei speichern möchte, fügen Sie --no-save hinzu: Der Worker hinterlässt das Ergebnis im Perso-Arbeitsbereich des Benutzers und überspringt den Download, wobei Kept on server, not saved: … → project <seq> gedruckt wird (die [project-ref]-Zeile wird weiterhin ausgegeben, sodass die Synchronisation später lippensynchronisiert oder abgerufen werden kann). Nur einzelne/ungespaltene Videos – die zusammengeführte Datei eines gespaltenen Videos benötigt einen lokalen Download, daher wird sie normal gespeichert und der Worker gibt dies an. Kann nicht mit --lipsync kombiniert werden (das lippensynchronisierte Video muss heruntergeladen werden).

Kostenloser Plan (Ergebnisse bleiben auf Perso) – Ein kostenloser Arbeitsbereich kann normal synchronisieren, lippensynchronisieren und trennen, aber der Server verweigert jeden Download, daher speichert der Worker dort nie eine Datei. Er druckt Free plan — <name>: … ready on Perso → <url> (downloads need a paid plan) – leiten Sie diesen Link als das gelieferte Ergebnis weiter: Der Lauf ist abgeschlossen, nichts ist fehlgeschlagen und es gibt nichts fortzusetzen. Wenn der Benutzer tatsächliche Dateien möchte, ist ein kostenpflichtiger Plan erforderlich – bieten Sie den Upgrade-Pfad an (siehe Plan-Upgrade & Credits), niemals einen erneuten Durchlauf.

Pausen im kostenlosen Plan ([free-limit]) – zwei davon, beide bevor etwas berechnet wird:

  • 30-Sekunden-Vorschau. Eine Synchronisations-/Lippensynchronisationseingabe länger als 30 s stoppt mit [free-limit]-Zeilen: Im kostenlosen Plan würden nur die ersten 30 Sekunden synchronisiert, der Rest weggelassen. Leiten Sie die Frage weiter, und bei Zustimmung führen Sie den gleichen Befehl mit --allow-preview erneut aus (der Worker schneidet die ersten 30 s lokal zu und sendet nur diese). Ein von Perso importierter Plattformlink kann nicht zugeschnitten werden – dort ist die Antwort eine lokale Datei, ein kürzerer Clip oder ein Upgrade.
  • Über das Planlimit. Medien, die das Längen-/Größenlimit des Plans überschreiten, erhalten kein Teilungsangebot im kostenlosen Plan (--allow-split gilt nicht): Die [free-limit]-Zeilen sagen, dass eine kürzere Datei oder ein Upgrade der einzige Weg ist. Leiten Sie sie weiter und stoppen Sie.

Während der Ausführung (zur Erklärung der Wartezeit):

  • Teilen: Die gesamte Datei wird zuerst hochgeladen; nur eine Ablehnung aufgrund des Planlimits installiert ffmpeg und teilt verlustfrei. Externe URLs (YouTube·TikTok·Drive·Vimeo) werden serverseitig verarbeitet.
  • Warteschlange: Alle Eingaben × Teile × Sprachen teilen sich einen Pool; eine volle Warteschlange wird alle 5 Minuten erneut überprüft. Ein Engine-Fehler bei einem Teil bricht die anderen Sprachen dieses Teils ab; ein stiller Teil übergibt das Original; eine Leerlaufüberwachung verhindert ewiges Hängen.
  • Speichern: Teile werden zu einer Datei pro (Eingabe × Sprache) zusammengeführt. Ein ungeteilter Ausgang behält den Perso-Dateinamen; ein zusammengeführter ist <original-name>.dubbed.<lang>.<ext>; Kollisionen erhalten _2,_3….

Lippensynchronisation

Lippensynchronisation (Mundbewegungen an die synchronisierte Audiospur angepasst) läuft nach der Synchronisation, am fertigen Synchronisationsprojekt. Nur Video – Audiodateien werden abgelehnt. Es ist ein langer Auftrag: Im Hintergrund ausführen und dem Benutzer vorab mitteilen, dass es erheblich länger dauert als die Synchronisation. Credits (Serverabrechnung ist maßgeblich): Synchronisation ≈ Sekunden ×1 · Lippensynchronisation ≈ ×2 · beides ≈ ×3 – Synchronisation jetzt + Lippensynchronisation später kostet dasselbe wie beides auf einmal. 4K+-Quellen: Jeder Satz ×3 auf Pro-/Business-/Enterprise-Plänen (z.B. eine 1-min 4K-Synchronisation+Lippensynchronisation ≈ 60×3×3 = 540) – erwähnen Sie dies, wenn das Video 4K ist.

Wählen Sie den Ablauf basierend auf dem, was vorhanden ist:

  1. Neues Video + Lippensynchronisation – Ein Befehl führt die gesamte Kette aus (Synchronisation → Lippensynchronisation → Speichern); warnen Sie, dass beide Stufen berechnet werden: node scripts/dubbing.mjs "<datei|URL>" --target en --lipsync Wenn [credit-check]-Zeilen gedruckt werden und es stoppt, übersteigt die Schätzung die verbleibenden Credits: Zeigen Sie diese Zeilen (Top-Up-URL inklusive) und führen Sie erneut mit --force aus, nachdem der Benutzer aufgestockt oder die Fortsetzung anderweitig genehmigt hat.
  2. Bereits in dieser Sitzung synchronisiert – Jeder abgeschlossene Lauf druckt eine [project-ref] {...}-Zeile. Behalten Sie sie; zeigen Sie sie dem Benutzer niemals an. Lippensynchronisation ohne erneute Synchronisation (×2, keine Synchronisationsgebühr): node scripts/dubbing.mjs --lipsync-only '<[project-ref] JSON>'
  3. Kein [project-ref] in dieser Sitzung – Fragen Sie, ob der Benutzer die Projektnummer aus dem Perso-Portal kennt (--lipsync-only <nummer>, ×2). Andernfalls muss das Video erneut synchronisiert werden (--lipsync, ×3) – bestätigen Sie vor der erneuten Synchronisation.

Regeln:

  • Wiederholte Lippensynchronisation am selben Projekt wird erneut berechnet (kein serverseitiges Deduplizieren). Wenn diese Sitzung es bereits lippensynchronisiert hat, verweisen Sie auf die vorhandene Datei und führen Sie nur bei expliziter Bestätigung erneut aus.
  • Wenn die Lippensynchronisation fehlschlägt, speichert der Worker stattdessen das synchronisierte Video und teilt dies im Abschlussbericht mit – leiten Sie dies klar weiter; die Synchronisations-Credits sind nicht verschwendet.
  • Credits laufen zwischen Synchronisation und Lippensynchronisation aus: Die synchronisierten Videos werden gespeichert, und die Fortsetzung schließt nur die Lippensynchronisation ab – leiten Sie die Top-Up-URL weiter und setzen Sie über den [resume-state]-Pfad fort, sobald bezahlt wurde (siehe Unterbrechung & Fortsetzung).

Sprecher (nur Synchronisationsprojekte)

Um einen neuen Sprecher einem oder mehreren Sätzen eines bereits synchronisierten Projekts zuzuweisen, führen Sie aus:

node scripts/speaker.mjs "<project URL|projectSeq>" --at "5s,22s,98s" (kommagetrennte Zeitcodes/-bereiche) node scripts/speaker.mjs "<project URL|projectSeq>" --text "first line|second line" (pipe-getrennt, zitierter Text) node scripts/speaker.mjs "<project URL|projectSeq>" --sentence 1234,1288 (erneuter Durchlauf nach einer [sentence-select]-Frage) node scripts/speaker.mjs "<project URL|projectSeq>" --list (die Sätze des Projekts durchsuchen, um das richtige Ziel zu finden)

Nur Synchronisationsprojekte – Der Worker lehnt Untertitel- (STT), Audiotrennungs- und Lippensynchronisationsprojekte sowie unfertige/fehlgeschlagene ab. Er ermittelt den Arbeitsbereich selbstständig aus dem Projektlink; Sie müssen nicht fragen, welcher Bereich.

Eine Pause ist kein Fehler. Eine [sentence-select]-Zeile bedeutet, dass der Worker kein einzelnes Ziel identifizieren konnte (nichts wurde angegeben, nichts stimmte überein oder mehr als ein Satz stimmte überein) – er beendet sich sauber, um Sie etwas zu fragen, nicht weil er fehlgeschlagen ist. Die nummerierte Liste darunter (Index, Zeitlabel, Text) kann dem Benutzer unverändert weitergegeben werden. Direkt nach dieser Liste druckt eine [sentence-ref]-Zeile eine JSON-Zuordnung derselben Nummern zu den internen Satznummern des Workers – diese Zeile ist nur für Ihre eigene Suche: Zeigen Sie sie niemals an und lesen Sie sie nicht vor. Sobald der Benutzer eine Nummer auswählt, schlagen Sie sie in dieser Zuordnung nach und führen Sie denselben Befehl mit --sentence auf diesen Wert gesetzt erneut aus. Ein [speaker-resolve]-Block daneben bedeutet, dass einige Ziele bereits aufgelöst wurden, aber noch nichts geschrieben wurde – er hat seine eigene nummerierte Liste und seine eigene [sentence-ref]-Zeile; die --sentence-Liste des erneuten Durchlaufs muss sowohl diese bereits aufgelösten Werte als auch die neu gewählten enthalten, da die aufgelösten sonst verworfen würden. Wenn ein Lauf mehr als eine [sentence-select]-Gruppe druckt (mehrere mehrdeutige Ziele gleichzeitig), wird jede Gruppe ...

[gekürzt für Übersetzung]

Individual skills in this repo

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

Verwandte Skills