Communitygithub.com

subtitle-translate — bilinguales ASS + Glossar

SRT / ASR-JSON / Video → bilinguales vereinfachtes Chinesisch + Original-ASS. Glossar, Doppelkorrektur, Annotationen.

Was ist subtitle-translate — bilinguales ASS + Glossar?

Video Localization Schritt 2: ywwzwb bilinguales ASS + Glossar-QA. Frisch vs. 26.09./24.09.

Funktioniert mit✓Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add ywwzwb/subtitle-translate-skill

In Ihrer bevorzugten KI fragen

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

Dokumentation

Untertitel-Übersetzung (Übersetzen von Untertiteln)

Überblick

Übersetzen Sie Untertiteldateien (SRT, ASR-JSON mit Wort-Zeitstempeln oder Video/Audio) in zweisprachige (vereinfachtes Chinesisch + Originalsprache) ASS-Untertitel. Der Ablauf ist fest in 6 Schritten vorgegeben, die vollständig und in der richtigen Reihenfolge ausgeführt werden müssen, ohne Schritte auszulassen oder die Reihenfolge zu ändern:

  1. Eingabe-Normalisierung + ASR-Transkription (Video/Audio; SRT überspringen; ASR erkennt Sprache automatisch)
  2. Zeitstempel → YAML (Skript + Modellprüfung, einschließlich Satzteilungs-Plausibilitätsprüfung)
  3. Korrekturlesen des Originaltextes + erneute Zeitstempel-Prüfung (zweites Abhören, Kreuzvalidierung; Fehler/Drift direkt im YAML korrigieren, inklusive Reparatur durch segmentierte Neutranskription)
  4. Batch-Übersetzung (Glossar + Anmerkungs-Untertitel)
  5. Korrekturlesen der Übersetzung
  6. Zusammenführen zu ASS (Skript)

Die Skripte befinden sich im scripts/-Verzeichnis dieses Skills (auf gleicher Ebene wie SKILL.md). Beim Ausführen eines Skripts bezieht sich <skill_dir> auf das Verzeichnis, in dem sich diese SKILL.md befindet.

Umgebung und Konfiguration

  • Erforderlich: ffmpeg, python (mit pyyaml) sowie das lokale ASR-Tool q3asr (Qwen3-ASR GGUF plattformübergreifende CLI).
  • Ausführungspriorität: run_transcribe.py --exe > Umgebungsvariable TRANSCRIBE_EXE > automatischer Download. Standardmäßig automatischer Download: Lädt je nach os/arch/Backend das q3asr-Binary aus den Releases von ywwzwb/qwen3-asr-universal herunter und speichert es im Cache unter ~/.cache/opencode-translate/asr/ (erster Download benötigt Internet, danach wird es wiederverwendet). Bei manueller Angabe setzen Sie TRANSCRIBE_EXE (Linux/macOS auf q3asr, Windows auf q3asr.exe) und müssen diese Datei nicht ändern.

Arbeitsverzeichnis (temporäre Isolation)

Jeder Übersetzungsauftrag erhält ein eigenes temporäres Arbeitsverzeichnis, in dem alle Zwischenprodukte gesammelt werden. Nach Abschluss wird es auf einen Schlag bereinigt:

  1. Verzeichnis erstellen: mkdir -p "$TEMP/opencode/<Basisname der Eingabedatei>" ($TEMP ist das temporäre Systemverzeichnis, unter Windows %TEMP%, z. B. C:\Users\zwb\AppData\Local\Temp; der Basisname ist der Dateiname ohne Erweiterung).
  2. Die Eingabedatei (Video/Audio/SRT) in dieses Verzeichnis kopieren. Alle folgenden Operationen werden innerhalb dieses Verzeichnisses ausgeführt.
  3. Alle Zwischenprodukte (mp3, txt, srt, json, main.yaml, seg*.yaml usw.) werden hier erstellt und verschmutzen nicht das Verzeichnis der Eingabedatei.
  4. Nach Abschluss wird die finale .ass-Datei in das Verzeichnis der Eingabedatei (oder an einen vom Benutzer angegebenen Ort) kopiert.
  5. Der Benutzer kann zur Bereinigung einfach das gesamte Arbeitsverzeichnis löschen.

Das Glossar bleibt davon unberührt: terminology.yaml wird global im Skill-Verzeichnis geteilt (siehe Schritt 4) und nicht in das Arbeitsverzeichnis gelegt.

Schritt 1: Eingabe-Normalisierung + ASR-Transkription

Bereiten Sie das Audio je nach Eingabetyp vor:

  • Video (mkv/mp4/mov usw.): Zuerst in Mono 16 kHz MP3 konvertieren: ffmpeg -y -i <input>.mkv -vn -map 0:a:0 -ac 1 -ar 16000 -c:a libmp3lame <input>.mp3
  • Audio (mp3/wav/m4a usw.): Ebenfalls in einheitliches Mono 16 kHz mp3 konvertieren, Ausgabe als <basename>.mono.mp3 (z. B. demo.mp3 → demo.mono.mp3), um Konflikte mit gleichnamigen Originaldateien zu vermeiden.
  • SRT: Diesen Schritt überspringen (keine Normalisierung oder ASR nötig), direkt zu Schritt 2 (Zeitstempel → YAML) gehen.

Wenn die Eingabe Audio/Video ist, ASR-Transkription ausführen (immer auf das oben normalisierte mp3 anwenden: Video: <input>.mp3, Audio: <basename>.mono.mp3):

python3 <skill_dir>/scripts/run_transcribe.py <audio>.mp3 -y

Fehlt die ASR-Laufzeit, wird automatisch das passende Zip für os/arch/Backend aus dem neuesten Release von ywwzwb/qwen3-asr-universal heruntergeladen und unter ~/.cache/opencode-translate/asr/ zwischengespeichert. Backend automatisch erkennen: Beim ersten Lauf wird die optimale Lösung für den Rechner ermittelt (cuda→vulkan→metal→cpu, basierend auf Existenz von nvidia-smi/vulkaninfo). Das Ergebnis wird in config.yaml im Skill-Verzeichnis gespeichert (wie terminology.yaml dauerhaft geteilt) und bei späteren Läufen direkt wiederverwendet; bei Maschinenwechsel wird eine leichte Überprüfung durchgeführt, bei Fehlschlag eine neue Erkennung gestartet. Standardmodell ist 1.7B, gemeinsam mit dem Backend in config.yaml gespeichert; beim ersten Lauf von q3asr automatisch heruntergeladen nach ~/.cache/q3asr/models/ (bei vorhandenem Cache wird dieser wiederverwendet). Überschreiben mit Umgebungsvariablen: TRANSCRIBE_BACKEND (cuda/vulkan/metal/cpu), TRANSCRIBE_MODEL (z. B. 1.7b/0.6b), TRANSCRIBE_ASR_VER (Standard latest). Manuelle Angabe von TRANSCRIBE_EXE hat weiterhin höchste Priorität.

  • Produziert gleichnamige <audio>.txt, <audio>.srt, <audio>.json (Wort-Zeitstempel [{text,start,end}], in Sekunden).
  • Segmentierte Neutranskription mit --out, um Überschreiben der Vollprodukt-Dateien zu vermeiden: run_transcribe.py benennt .txt/.srt/.json nach dem Namen der eingegebenen Audiodatei. Bei einer Fenster-Neutranskription (--seek-start) für dasselbe mp3 würde ohne --out das Vollprodukt <audio>.json überschrieben werden. Mit --out <Name> (z. B. --out seg1) wird das Audio als <Name>.mp3 kopiert und transkribiert, die Ausgabedateien landen als <Name>.json usw., das Vollprodukt-JSON bleibt erhalten.
  • ASR erkennt Sprache automatisch (Qwen3-ASR unterstützt mehrere Sprachen); zum Erzwingen einer Sprache -l <Sprache> übergeben.
  • Lange Audiodateien: Zuerst mit ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 <audio>.mp3 die Dauer ermitteln und dem Bash-Befehl ein ausreichend großes Timeout geben (lokales 1.7B-Modell etwa 0,05× Audiodauer in Sekunden plus Modellinitialisierung).

Fehlerbehebung

  • ASR fehlgeschlagen (Exit-Code ungleich 0): Bei Fehlschlag von run_transcribe.py wird automatisch das Ende von logs/latest.log ausgegeben; anhand des Logendes lokalisieren; bei GPU-/Grafikstack-bezogenen Fehlern mit --no-dml --no-vulkan erneut versuchen.
  • Automatisch heruntergeladene Laufzeit kann nicht starten (z. B. fehlende libllama.so mit Fehler Failed to load dynlib/dll): Eine lokal verfügbare q3asr-Installation oder bereits entpackte Laufzeit verwenden und TRANSCRIBE_EXE darauf setzen; diese Datei muss nicht geändert werden.
  • Müllzeichen !!! / Bildschirmflackern: Umgebungsvariable GGML_VK_DISABLE_F16=1 setzen und erneut transkribieren (Vulkan deaktiviert fp16, um Inkompatibilitäten mit einigen Treibern zu vermeiden).
  • ffmpeg nicht vorhanden: Sofort stoppen, zuerst ffmpeg installieren und sicherstellen, dass es im PATH ist, dann Schritt 1 fortsetzen.

Schritt 2: Zeitstempel → YAML

Je nach Quelle das passende Skript wählen:

  • Audio/Video-Quelle (<audio>.json): Ausführen python3 <skill_dir>/scripts/timestamp_to_yaml.py <audio>.json main.yaml (optional --max-width für maximale Zeilenbreite, Standard 30; --gap für Pausenschwelle in Sekunden, Standard 1,5)
  • SRT-Quelle: Ausführen python3 <skill_dir>/scripts/srt_to_yaml.py <input>.srt main.yaml

Erzeugt die Zwischendatei main.yaml:

main:
  - from: 00:00:02,003
    to: 00:00:05,069
    en: |
      Narrator:
      TODAY ON "HOW IT'S MADE"...
  - from: 00:00:26,227
    to: 00:00:28,026
    en: |
      ALUMINUM FOIL...

Nach der Konvertierung sofort einen Kollaps-Check durchführen (Skript, unbedingt vor manueller Überprüfung): ASR-Zeitstempel kollabieren häufig – mehrere Cues drängen sich in dieselbe Sekunde (sogar mit Dauer Null), Text ist verstümmelt. Vor der mechanischen Überprüfung zuerst das Skript laufen lassen:

python3 <skill_dir>/scripts/check_collapse.py main.yaml

  • Erkennt: zero (Dauer Null, from==to), cluster (3+ Cues teilen denselben Startzeitpunkt = vollständiger Kollaps), order (Reihenfolge fehlerhaft), overlap (Zeitüberlappungen).
  • Exit-Code: 0 bei sauberem Zustand, 1 bei Problemen. Bei zero/cluster gemäß Schritt 3 ("Segmentierte Neutranskription als Reparatur") den Bereich behandeln.
  • Die aus einer Fenster-Neutranskription stammenden seg*.yaml-Dateien mit --strict erneut prüfen (Alarm schon bei 2 Cues in derselben Sekunde): python3 <skill_dir>/scripts/check_collapse.py seg.yaml --strict – auch die Fenster-Neutranskription selbst kollabiert oft am Ende; vor dem Zusammenfügen zuerst selbst prüfen.

Nach der Konvertierung muss eine Überprüfung (Modellbewertung) erfolgen: Das Skript teilt Sätze automatisch an Punkten, Ausrufezeichen, Fragezeichen oder langen Pausen, teilt zu lange Sätze automatisch nach Breite auf und hat bereits zu kurze Fragmente automatisch zusammengeführt (einsame Fragmente innerhalb eines Satzes werden an benachbarte angehängt, einsame Einzelzeichen ohne Satzendzeichen werden an den nächsten Satz angehängt). Das Konvertierungsskript enthält eine automatische Zusammenführung "hängen gebliebener" Satzteile: ASR/Breitenteilung schneidet Sätze oft an Funktionswörtern ab (Endung mit the/a/to/any/each/boil/known usw.) oder erzeugt nach einem halluzinierten Punkt klein weitergeschriebene Fortsetzungen (plasters./is applied.), oder hinterlässt einzelne Wortköpfe (Plasters/are made of...). timestamp_to_yaml.py führt diese Fragmente automatisch mit dem nächsten Satz zusammen, um den manuellen Arbeitsaufwand zu reduzieren. Bei der Überprüfung: prüfen, ob die Satzteilung natürlich ist; zu lange oder unnatürlich geteilte Sätze neu aufteilen (bevorzugt an weichen Trennstellen wie Aufzählungskommas oder Kommas).

  • Extrem kurze Fragmente müssen zusammengeführt werden: Wenn ein Cue nur 1-2 Wörter enthält oder eindeutig ein Fragment aus einem vollständigen Satz ist (z. B. ein einzelnes Mercury,, The), mit edit in den vorherigen oder nächsten Satz einfügen, sodass jeder Untertitel eine vollständige Sinneinheit bildet. Kurze Titelsätze (Cheese., Tights.) sind ausgenommen.
  • Audio/Video-Quelle: Bei erneuter Aufteilung muss das ursprüngliche JSON gelesen werden, um die from/to-Zeiten jedes Teilfragments anhand der Wort-Token-Start- und Endzeiten zu aktualisieren (SRT hat keine Wort-Zeitstempel, dieser Punkt gilt nicht).

Satzteilungs-Plausibilitätsprüfung (jeden Cue einzeln beurteilen, muss durchgeführt werden): Das Skript teilt mechanisch nach Breite/Pause, schneidet dabei oft Sätze mitten durch. Jeden Cue anhand der folgenden Kriterien prüfen; bei Unangemessenheit mit edit zusammenführen oder Teilungspunkt verschieben:

  • Jeder Cue muss eine vollständige Sinneinheit sein: Darf nicht mit einem freistehenden Präposition/ Konjunktion enden. Steht am Zeilenende and, or, as, where, which, before, to, of, into usw., ist der Teilungspunkt falsch; das Wort sollte in die nächste Zeile oder vollständig zusammengeführt werden.
  • Teilungspunkte vor Nebensatz-/Parallelkonjunktionen setzen, nicht danach. Beispiel: assure quantity distribution / before they're carried... (nicht ...distribution before / they're carried...); come down 2,000 times per minute / to cut a total of 8,000... (nicht ...to cut a / total of 8,000...).
  • Präpositionalphrasen derselben Sinneinheit nicht trennen: 5 hours of work als Ganzes belassen, nicht in 5 hours / of work aufteilen; the brush and roller area nicht in the brush and / roller area aufteilen.
  • Fragment, das erst nach Zusammenführung einen vollständigen Satz ergibt, zusammenführen: Z. B. ...cuts the billet strips into + small, equal-sized pieces. zu einem Cue zusammenführen; ...responsible for the + cloudiness of the beer. zusammenführen.
  • Chinesische Satzteilung spiegelt die englische wider: Die Zeilengrenze der chinesischen Übersetzung sollte mit dem englischen Cue übereinstimmen, das Zeilenende darf ebenfalls nicht freistehend sein (z. B. 按量分配, gefolgt von 随后被送往..., sollte 随后 in die nächste Zeile verschoben werden; 落下2000次,切割出 sollte geändert werden zu 落下2000次 / 短短60秒内总计切割出8000根).
  • Nach Zusammenführung/Verschiebung des Teilungspunkts muss das ursprüngliche JSON gelesen werden, um from/to anhand der Wort-Token-Start- und Endzeiten des neuen Fragments zu aktualisieren.

Schritt 3: Korrekturlesen des Originaltextes

Lesen Sie jedes en-Feld Satz für Satz durch, suchen Sie Rechtschreibfehler, Hörfehler, fehlende Wörter und korrigieren Sie en in main.yaml direkt mit dem edit-Werkzeug. Listen Sie die Änderungspunkte in der Antwort auf. Es ist verboten, nur einen Hinweis zu geben, ohne den Originaltext zu ändern.

Behalten Sie das Standardformat von main.yaml bei ( - from: + en: |-Block, siehe Beispiel in Schritt 2): Nur lokale Edits durchführen, das gesamte File nicht mit Skripten neu formatieren (z. B. yaml.safe_dump neu schreiben), um Einrückungen und Block-Skalar-Format nicht zu beschädigen.

Segmentierte Neutranskription als Reparatur (Halluzinationen/fehlerhafte Zeitstempel)

Finden Sie eine defekte Region (Cue mit ungewöhnlich langer Dauer, Textmüll, Zeitüberlappungen der Cues):

  1. Fenster wählen: Beginn des defekten Bereichs etwa 3s nach vorne, Ende etwa 3s nach hinten verschieben, erhalte X und D = Ende - X.
  2. Diesen Abschnitt neutranskribieren (unbedingt mit --out, sonst wird das Vollprodukt <audio>.json überschrieben): python3 <skill_dir>/scripts/run_transcribe.py <audio>.mp3 --seek-start X --duration D --out seg1 -y (Zeitstempel relativ zum Segmentanfang, Ausgabe ist seg1.json).
  3. Selbstprüfung des neu transkribierten Segments: python3 <skill_dir>/scripts/check_collapse.py seg1.yaml --strict. Fenster-Neutranskription kollabiert oft selbst (mehrere Cues drängen sich in dieselbe Sekunde); bei zero/cluster zuerst das Fenster verkleinern und erneut transkribieren, nicht weiter zusammenfügen.
  4. Absolute Zeit wiederherstellen: python3 <skill_dir>/scripts/timestamp_to_yaml.py seg1.json seg.yaml --offset X (Skript führt hängengebliebene Satzteile automatisch zusammen, siehe Schritt 2).
  5. Abdeckung prüfen: Nach --offset sollte das to des letzten Cues in seg.yaml ≈ X + D sein. Deutlich früher als X + D (Ausgabe der Neutranskription abgeschnitten) → Fenster vergrößern und erneut transkribieren, nicht weiter zusammenfügen.
  6. Zusammenfügen (unbedingt mit Fensterparametern): python3 <skill_dir>/scripts/splice_yaml.py main.yaml seg.yaml main.new.yaml --seek-start X --duration D. Das Skript löscht basierend auf dem angeforderten Fenster, nicht auf dem Inhaltsbereich des Segments, und überprüft die Abdeckung – falls das neu transkribierte Segment abgeschnitten wurde, meldet das Skript einen Fehler und verweigert das Zusammenfügen (notfalls mit --force, aber zuerst das Fenster vergrößern und erneut transkribieren).
  7. Überprüfung: Ausgabe von splice prüfen (Liste der gelöschten Cues + Wortanzahl-Warnung + LOSS-Zeilen). Jeder splice gibt standardmäßig die Liste der gelöschten Cues aus; erscheint eine LOSS:-Zeile, bedeutet das, dass der Text eines gelöschten Cues im neu transkribierten Inhalt nicht vorkommt – wenn es ein vollständiger Satz ist, Fenster vergrößern und erneut transkribieren. Erscheint eine BOUNDARY:-Zeile, bedeutet das, dass ein gelöschter Cue die Fenstergrenze überschreitet (Start vor dem Fenster oder Ende nach dem Fenster), sein Inhalt könnte mitten durchgeschnitten worden sein – prüfen, ob das Fenster den Cue tatsächlich abdeckt, sonst Fenster vergrößern und erneut transkribieren. Nach Bestätigung, dass keine Wörter fehlen, mit edit den Inhalt von main.yaml durch main.new.yaml ersetzen; bei Wortverlust Fenster vergrößern und erneut transkribieren oder manuell mit edit korrigieren.

Zusammenfügen unbedingt mit splice_yaml.py, manuelles Einfügen neu transkribierter Segmente verboten: Das manuelle Einfügen neuer Cues in main.yaml führt leicht zu doppelten/überlappenden Cues (derselbe from erscheint zweimal); das Ersetzen über das Zeitfenster mit dem Skript vermeidet dies. Tritt nach dem Ersetzen ein doppelter from auf, wurde zu viel zusammengefügt; mit splice wiederholen.

Erneute Zeitstempel-Prüfung (zweites Abhören, Kreuzvalidierung)

Zwei aufeinanderfolgende Transkriptionen derselben Audiodatei ergeben deutlich driftende Wort-Zeitstempel (gemessen: max delta zwischen zwei Durchläufen kann Dutzende Sekunden betragen, einige Cues unterscheiden sich um 12-40s). Daher sind die Zeitstempel aus einem Durchlauf nicht vollständig vertrauenswürdig. Nach der Erstellung des YAML muss ein zweiter vollständiger Transkriptionsdurchlauf durchgeführt werden, um die Zeitstempel mit den aktuellen Cues kreuzzuvalidieren:

  1. Audio für zweiten Durchlauf kopieren (erstes JSON nicht überschreiben): cp <audio>.mp3 <audio>.pass2.mp3, dann python3 <skill_dir>/scripts/run_transcribe.py <audio>.pass2.mp3 -y, Ausgabe <audio>.pass2.json (oder --out pass2 verwenden, um das manuelle cp zu sparen, gleicher Effekt).
  2. Cue für Cue prüfen: python3 <skill_dir>/scripts/compare_timestamps.py main.yaml <audio>.pass2.json --threshold 1.0. Das Skript lokalisiert das en jedes Cues anhand des normalisierten Texts in den Wort-Token des zweiten Durchlaufs und gibt delta start/end aus (Zeit des aktuellen Cues − Wort-Zeit des zweiten Durchlaufs) mit <<<-Markierung. Standardschwelle ist 1,0s (der zweite Durchlauf driftet selbst, 0,5s ergäbe zu viele falsch Positive).
  3. Bei Cues mit <<< oder NOT FOUND präzise Korrektur durchführen: Das zweite Abhören ist nur ein Detektor, keine Autorität – es driftet selbst (das gesamte Segment kann insgesamt versetzt sein), daher dürfen die Zeitstempel des zweiten Durchlaufs nicht direkt zur Korrektur von from/to verwendet werden. Stattdessen immer nach dem oben beschriebenen Ablauf "Segmentierte Neutranskription als Reparatur" für dieses Fenster vorgehen: Fenster etwa 3s vor und nach dem Cue neu transkribieren → mit --offset absolute Zeit wiederherstellen → mit splice_yaml.py zusammenfügen, das Ergebnis der Fenster-Neutranskription als maßgeblich verwenden. Stimmt die Fenster-Neutranskription mit dem zweiten Durchlauf überein, sind die Zeiten im Haupt-YAML tatsächlich falsch; korrigieren. Bestätigt sie, dass das Haupt-YAML richtig ist, nicht ändern.
  4. Kreuzvalidierung auf der Übersetzungsseite: compare_timestamps.py kann mit --full für jedes YAML die Deltas aller Cues ausgeben, um den Drift-Trend insgesamt zu erfassen.
  5. Wiederholen, bis keine <<< und keine NOT FOUND mehr vorhanden sind (oder manuell bestätigt).

Hinweis: Auch das zweite Abhören kann selbst driften oder abweichenden Text liefern (daher NOT FOUND), daher ist letztlich die segmentierte Fenster-Neutranskription + manuelles Abhören maßgeblich; compare_timestamps.py ist nur ein Detektor, um verdächtige Cues schnell zu finden.

Schritt 4: Batch-Übersetzung

Vor Beginn der Übersetzung <skill_dir>/terminology.yaml lesen (leere Datei erstellen, falls nicht vorhanden). Das Glossar befindet sich im Verzeichnis dieses Skills (bei globaler Installation maschinenweit) und wird über Videos, Projekte und Sitzungen hinweg dauerhaft geteilt, um eine konsistente Übersetzung von Personen-/Orts-/Eigennamen in verschiedenen Videos zu gewährleisten. Wenn während der Übersetzung ein neuer Begriff auftaucht, diesen zuerst in <skill_dir>/terminology.yaml eintragen und dann verwenden; die Groß-/Kleinschreibung wird ignoriert.

Hinweis: Wenn <skill_dir> sich vom aktuellen Projekt unterscheidet (globale Installation), ist das Glossar die einzige globale Instanz; es wird kein separates terminology.yaml im Projekt gepflegt.

Die Übersetzung erfolgt im strukturierten Batch-Output mit Skript-Schreiben, nicht Satz für Satz mit edit:

  1. Batch-Übersetzung (max. 50 Sätze pro Batch): In der Antwort einen strukturierten Übersetzungsblock ausgeben – start ist die 0-basierte Cue-Nummer des ersten Satzes dieses Batches in main.yaml, translation-Liste entspricht Satz für Satz in der gleichen Reihenfolge wie die Cues in main.yaml. Es ist verboten, auf einmal die Übersetzung aller Untertitel auszugeben. Nach Fertigstellung eines Batches und Bestätigung (Skript-Schreiben + Stichprobenprüfung) den nächsten Batch bearbeiten.
start: 0            # Cue-Nummer des ersten Satzes dieses Batches (0-basiert)
translation:
  - Übersetzung Satz 1
  - Übersetzung Satz 2
  - |
    Erste Zeile der mehrzeiligen Übersetzung
    Zweite Zeile der mehrzeiligen Übersetzung
  - Übersetzung Satz 4
  1. Skript-Schreiben: Den obigen strukturierten Block als batch.yaml speichern (im Arbeitsverzeichnis) und ausführen: python3 <skill_dir>/scripts/apply_translations.py main.yaml batch.yaml main.new.yaml Das Skript fügt das chs-Feld präzise nach jedem en-Block anhand der Cue-Nummer ein, ohne die Datei neu zu formatieren (nicht safe_dump), Anmerkungen und andere Zeilen bleiben unverändert. Nach Prüfung cp main.new.yaml main.yaml.

    • --overwrite: Vorhandene chs ersetzen (Standardmäßig wird bei vorhandenem chs ein Fehler gemeldet, um versehentliches stilles Überschreiben zu verhindern)
    • --dry-run: Nur ausgeben, wie viele Einträge geschrieben würden, ohne zu speichern
    • Das Skript prüft, ob start + Anzahl den Rahmen nicht überschreitet; bei Überschreitung Fehlermeldung, anhalten und start prüfen
  2. Vor dem endgültigen Übernehmen der Übersetzung selbst prüfen: Jede Übersetzung muss die unten stehenden Übersetzungsregeln einhalten (kein Punkt/Komma am Satzende, Zahlen arabisch, Glossar-Konsistenz, Zeilengrenzen spiegeln englischen Cue wider). Nach Fertigstellung eines Batches manuell die ersten und letzten Übersetzungen des Batches stichprobenartig prüfen und bestätigen, dass die Cue-Nummern mit dem Inhalt übereinstimmen (insbesondere prüfen, ob start im Übersetzungsblock gleich start + Anzahl des vorherigen Batches ist).

Die endgültige Prüfung erfolgt dennoch mit dem edit-Werkzeug Satz für Satz – das Batch-Schreiben dient zum "Einfüllen", die manuelle edit zum "Feintuning".

main:
  - from: 00:00:02,003
    to: 00:00:05,069
    en: |
      Narrator:
      TODAY ON "HOW IT'S MADE"...
    chs: |
      旁白:
      今天的《造物小百科》……

Übersetzungsregeln

  1. Sinngemäße Übersetzung priorisieren, nicht wortwörtlich. Wortstellung und Position je nach chinesischem Satzbau und Satzlänge anpassen; Sätze können zusammengefasst oder geteilt werden, um einen flüssigen und natürlichen chinesischen Satz zu gewährleisten.
  2. Eigennamen einheitlich über das Glossar verwenden. Personen-, Orts-, Werk-, Markennamen usw. in terminology.yaml einheitlich übersetzen und vor jeder Übersetzung zuerst lesen. Die Begriffssuche ignoriert Groß-/Kleinschreibung. Neue Begriffe vor der Verwendung zuerst zum Glossar hinzufügen:
terminology:
  Susan: 苏珊
  Texas: 德州
  HOW IT'S MADE: 造物小百科
  1. Satzendzeichen. Wenn das letzte Zeichen eines Übersetzungstextes ein Punkt 。 oder ein Komma (vollbreit , oder halbbreit ,) ist, dieses direkt entfernen. Beispiel: "欢迎收看本期节目。" → "欢迎收看本期节目". Punkte/Kommas sind nur im Satzinneren erlaubt, nicht als Satzendezeichen der Übersetzung.
  2. Zahlen in arabischen Ziffern schreiben. Zahlen in der Übersetzung nach Möglichkeit in arabischen Ziffern schreiben: 三到八小时 → 3-8 小时、二十年前 → 20 年前、六千克面粉 → 6000 克面粉、百分之九十五 → 95%、四点四米 → 4.4 米、750 摄氏度 → 750 摄氏度. Ausgenommen sind Zahlen in Eigennamen/Titeln (z. B. "How It's Made", Jahreszahlen, Modelle).
  3. Anmerkungs-Untertitel. Bei im chinesischen Kontext seltenen lokalen Bräuchen, Feiertagen, Fachbegriffen, angloamerikanischen Maßeinheiten usw. im Untertitel eine kurze Anmerkung von maximal 20 Zeichen (etwa 4 Zeichen pro Sekunde) hinzufügen und in die annotations-Liste in main.yaml eintragen. Derselbe Begriff wird nur beim ersten Auftreten mit einer Anmerkung versehen.
annotations:
  - from: 00:00:02,003
    text: 造物小百科:科普纪录片栏目

Anmerkungsregeln:

  • Jede Anmerkung maximal 20 Zeichen, so präzise wie möglich.
  • from mit der Startzeit des entsprechenden Untertitel-Cues abgleichen.
  • to muss nicht ausgefüllt werden; yaml_to_ass.py berechnet die Endzeit automatisch mit 4 Zeichen/Sekunde.
  • Treten bei demselben Satz (gleiche Startzeit) mehrere Anmerkungen auf, führt das Skript diese zu einem Ereignis zusammen, das übereinander angezeigt wird.
  • Überschreitet die Endzeit einer Anmerkung die Startzeit der nächsten, klemmt das Skript die Endzeit der vorherigen auf den Beginn der nächsten (vor dieser), um zeitliche Überlappungen zu vermeiden.
  • Angloamerikanische Maßeinheiten: Die Anmerkung gibt direkt die standardisierte SI-Einheitenumrechnung für den konkreten Zahlenwert des Satzes an, z. B. "500磅≈227公斤", "60英里≈96.6公里/时", "62°F≈17°C"; erklärt nicht die Bedeutung der Einheit selbst (wie "britische Gewichtseinheit"). Bei Einheitenumrechnungen wird ≈ zur Angabe der Näherung verwendet; unterschiedliche Zahlenwerte müssen jedes Mal umgerechnet werden, Ausnahme "nur beim ersten Auftreten" gilt hier nicht.

Schritt 5: Korrekturlesen der Übersetzung

Alle chs vollständig durchlesen, auf Übersetzungsfehler, Auslassungen, inkonsistente Terminologie, falsche Zeitachsen prüfen und mit dem edit-Werkzeug korrigieren.

Nach dem Korrekturlesen das gesamte main.yaml noch einmal durchgehen und Zahlen, die sich für arabische Ziffern eignen, direkt mit edit in arabische Ziffern umwandeln:

  • Zahlen als englische Wörter in en (Hörtranskript): three to eight hours → 3 to 8 hours、six thousand kilos → 6,000 kilos、twenty years ago → 20 years ago、half a centimeter → 0.5 centimeter、seventy-five → 75、first/second → 1st/2nd.
  • Zahlen als chinesische Zeichen in chs (Übersetzung): 二十年前 → 20 年前、三到八小时 → 3-8 小时、六千公斤 → 6000 公斤、百分之九十五 → 95%、四点四米 → 4.4 米.
  • Zahlen in Eigennamen/Titeln/Jahreszahlen/Modellen unverändert lassen (z. B. "How It's Made", Jahreszahlen in Narrator:).
  • Nur eindeutige Fälle ändern; bei Unsicherheit den Originaltext beibehalten.

Schritt 6: Zusammenführen zu ASS

Ausführen: python3 <skill_dir>/scripts/yaml_to_ass.py main.yaml output.ass --check

--check prüft die Cue-Integrität (Überlappungen / Dauer Null / Reihenfolgefehler); bei Fehlern wird eine Meldung ausgegeben und das Programm beendet, um die Ausgabe einer fehlerhaften Datei zu verhindern. Nach dem Zusammenführen die fertige .ass-Datei in das Verzeichnis der Eingabedatei kopieren (z. B. neben das Video), damit der Benutzer sie direkt verwenden kann; die Zwischenprodukte im Arbeitsverzeichnis kann der Benutzer nach Bedarf bereinigen.

Erzeugtes Format (Vorlage ist im Skript eingebettet, die wichtigsten Punkte sind):

[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
WrapStyle: 2

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Translation,Noto Sans CJK SC,56,&H00FFFFFF,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,3,1,2,80,80,81,1
Style: Original,Noto Sans CJK SC,36,&H00FFFFFF,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,2,1,2,80,80,45,1
Style: Annotation,Noto Sans CJK SC,26,&H00FFE066,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,1,1,7,40,40,20,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

Ausgabe als drei unabhängige Spuren, um eine nachträgliche Anpassung der Stile Spur für Spur zu ermöglichen (jede Spur verwendet eigene Layer und Styles, können in Aegisub/Schnittsoftware separat bearbeitet werden):

LayerStyleInhaltSchriftgröße/Position
0TranslationVereinfachtes Chinesisch (Übersetzung)fs56, Hauptzeile unten
1OriginalText in Originalsprachefs36, direkt unter der Übersetzung
2AnnotationAnmerkungfs26, obere linke Ecke

Layout-Anforderungen:

  • Übersetzung ist primär: Große Schrift unten (Layer 0).
  • Original ist sekundär: Kleine Schrift unter der Übersetzung (Layer 1).
  • Anmerkungen in der oberen linken Ecke (Layer 2, Alignment 7).

Beispielereignis:

Dialogue: 0,0:00:02.00,0:00:05.06,Translation,,0,0,0,,今天的《造物小百科》……
Dialogue: 1,0:00:02.00,0:00:05.06,Original,,0,0,0,,Narrator: TODAY ON "HOW IT'S MADE"...
Dialogue: 2,0:00:02.00,0:00:03.62,Annotation,,0,0,0,,造物小百科:科普纪录片栏目

Häufige Fehler (Common Mistakes)

FehlerRichtiges Vorgehen
YAML übersprungen und direkt ASS ausgegebenErst main.yaml konvertieren, dann übersetzen, dann zusammenführen
ASS manuell statt per Skript geschriebenMit yaml_to_ass.py zusammenführen, Anmerkungszeiten werden vom Skript berechnet
Vor ASS-Ausgabe keine IntegritätsprüfungMit yaml_to_ass.py --check auf Überlappungen/Dauer Null/Reihenfolgefehler prüfen
Alle Untertitel auf einmal übersetztMax. 50 Sätze pro Batch, strukturierten Übersetzungsblock ausgeben, per Skript schreiben
chs einzeln mit edit geschriebenMit apply_translations.py batch-schreiben, edit nur für die endgültige Prüfung verwenden
Batch-start-Nummer falschstart muss = start des vorherigen Batches + Anzahl des vorherigen Batches sein; bei Überschreitung meldet das Skript einen Fehler
Vorhandene Übersetzung still überschriebenStandardmäßig wird bei vorhandenem chs ein Fehler gemeldet; nur bei sicherer Notwendigkeit --overwrite verwenden
Inkonsistente Übersetzung von Personen-/OrtsnamenIn terminology.yaml eintragen, vor jeder Übersetzung zuerst lesen
Anmerkung länger als 20 ZeichenKürzen, nur notwendige Informationen behalten
Endzeit der Anmerkung willkürlich eingetragenVom Skript mit 4 Zeichen/Sekunde berechnen lassen
Mehrere Anmerkungen zum selben Satz nicht übereinander angezeigtSkript führt automatisch zu zwei übereinanderliegenden Zeilen zusammen
Trennungspräpositionen am Zeilenende nicht korrigiertSplice-Punkte an Konjunktionen/Nebensatzgrenzen setzen, nicht nach freistehenden Präpositionen
Nach Zusammenführung/Verschiebung des Teilungspunkts keine ZeitaktualisierungUrsprüngliches JSON lesen und from/to aktualisieren
Im zweiten Durchlauf gefundene Abweichungen nicht korrigiertcompare_timestamps.py ist nur ein Detektor; Korrektur durch segmentierte Fenster-Neutranskription

Ausführungsreihenfolge (Ablauf)

  1. Schritt 1: Eingabe normalisieren + ASR-Transkription (für Video/Audio)
  2. Schritt 2: Zeitstempel → YAML konvertieren + Kollaps-Check + Satzteilungs-Plausibilitätsprüfung
  3. Schritt 3: Originaltext Korrektur lesen + erneute Zeitstempel-Prüfung (zweites Abhören) + segmentierte Neutranskription (falls nötig)
  4. Schritt 4: Batch-Übersetzung (Glossar + Anmerkungs-Untertitel)
  5. Schritt 5: Übersetzung Korrektur lesen + Zahlen normalisieren
  6. Schritt 6: Zusammenführen zu ASS + Ausgabe-Kopie

Jeder Schritt muss nacheinander ausgeführt werden, keine Schritte überspringen oder die Reihenfolge vertauschen.

Verwandte Skills