MMD-Tanzvideo-Untertitel: End-to-End-Workflow
0. Ein-Satz-Prinzip
Nach dem Schreiben/Rendern muss ein Einzelbild zur Überprüfung extrahiert werden: ffprobe-Dauer übereinstimmend ≠ Untertitel tatsächlich sichtbar. Fehler im ASS-Zeitstempel oder Style-Farbformat führen zu „Rendering erfolgreich, aber kein Text“. Dieses Projekt hat mehrfach die Erfahrung gemacht, dass etwas „korrigiert“ wurde, aber nicht eingebrannt wurde. Die Abnahme erfolgt daher immer anhand von extrahierten Einzelbildern.
1. Assets und Pfade (dieser Arbeitsbereich)
| Element | Pfad |
|---|---|
| Untertitelprojekt | D:\yingyong2\论项目\字幕\ |
| LRC-Text | 字幕\[by维尔日记].txt – KISS OF LIFE《Who is she (Japanese Ver.)》, 36 Zeilen |
| Altes MMD-Video | 字幕\0001-4956 - 副本.mkv (2560×1080 / 30fps; Datei unvollständig, angegeben 165s, tatsächlich nur ~137s dekodierbar) |
| Neues MMD-Video | D:\mmd.mp4\0002-4956.mkv (2560×1080 / 30fps / 165.166s, vollständig) |
| Schriftarten | 字幕\build\fonts\ (Anton, ArchivoBlack, BebasNeue, Bungee, Monoton, PermanentMarker, RubikGlitch, Silkscreen, PirataOne, UnifrakturCook) + System Georgia / Microsoft YaHei |
| Generierungsskripte | 字幕\build\*.py |
| Videoausgabe | 字幕\输出\<Aufgabenname>\ (ein Ordner pro Aufgabe, Auslieferungsname mit lesbarem chinesischen Namen) |
| ffmpeg | C:\Users\35530\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-9.0-full_build\bin\ffmpeg.exe |
| python | C:\Users\35530\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\python\python.exe (PIL 12.3 / numpy 2.3, kein cv2) |
2. Sieben-Schritte-Hauptablauf
① Quellmaterial analysieren ffprobe Auflösung/Bildrate/Dauer/Farbraum; Dekodierungstest zur Erkennung abgeschnittener Dateien
② Segment auswählen Liedabschnitt vs. Tanzbewegung; Demo 5s / 30s / gesamtes Video
③ Text zuordnen LRC absolute Zeit → Segmentstart subtrahieren = ASS relative Zeit
④ Stil festlegen Referenzen S1–S6 (siehe style-frames-compare); zuerst statische Einzelbilder, dann dynamisch
⑤ ASS schreiben Python-Generierung; Format-Hard-Regeln aus ass-render-playbook befolgen
⑥ Rendern ffmpeg einbrennen (oder transparente Überlagerung); zuerst 5–10s zur Validierung, dann gesamter Abschnitt
⑦ Abnahme Einzelbild extrahieren (mindestens 1 Frame pro Textzeile) + Keyframe-Tabelle erstellen; Komposition prüfen, kein Chinesisch, Gesicht nicht verdecken, Ausblenden am Ende
① Quellmaterial analysieren
$ff='...\ffmpeg.exe'; $fp='...\ffprobe.exe'
& $fp -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,nb_frames,pix_fmt,color_space -show_entries format=duration -of default=nw=1 $v
& $ff -v error -i $v -map 0:v:0 -c copy -f null NUL # Meldung "File ended prematurely" = abgeschnitten
- Alle Materialien in diesem Projekt sind 2560×1080 / 30fps / h264 yuv420p / bt709, ultrabreit 64:27.
- 165s Video ≈ 4956 Frames; 30s Video = 900 Frames.
② Segment auswählen
- LRC erster Refrain:
36.892 / 40.366 / 44.003 / 47.577 / 51.179 / 54.698 / 58.309 / 61.926, bis ~66s Ende. - 5s Vergleichs-Demo häufig
0:58.2–1:03.2; 30s-Demo häufig0:36.5–1:06.5; gesamtes Video 0–154.6s (alte Datei nur bis 137s). - Zuschneiden:
-ss 36.5 -t 30 -i src -vf "eq=brightness=-0.05:contrast=1.04:saturation=1.02" -c:v libx264 -crf 16 -pix_fmt yuv420p(Leichte Abdunklung für Kontrast bei weißen/cremefarbenen Buchstaben; vollständige Farbkorrektur siehe subject-color-grade)
③ Text zuordnen
LRC ist absolute Zeit; ASS verwendet relative Zeit zum Segmentstart. Beispiel: Segment beginnt bei 36.5s, dann 36.892 → 0.392s.
Ein Cue pro Zeile; innerhalb der Zeile Aufteilung in mehrere Events pro Wort (siehe unten). Das End-Event sollte 0.14–0.4s vorher enden, um ein Überlappen der Zeilen zu vermeiden.
④ Stil festlegen
- Zuerst
style-frames-compare-Skill lesen, je nach gewünschter Stimmung S1–S6 auswählen, zuerst statische Einzelbilder zur Ansicht erstellen. - Wichtige Einschränkung: Wenn der Benutzer explizit „kein Chinesisch" sagt, nur den ursprünglichen englischen/japanischen Text des Liedes behalten; Person in der Mitte, große Buchstaben in der linken/rechten Sicherheitszone und den oberen/unteren Ecken.
- Bereits vorhandene, wiederverwendbare Generatoren:
styles_anim.py(S2/S4/S6 5s-Animation),flare_wide.py(Spektakel),neon_wide.py(Neon),avoid_side2.py(vollständige Vermeidung),kpop_styles.py(statischer Entwurf),art_frames.py(künstlerischer statischer Entwurf).
⑤ ASS schreiben
- Mit Python generieren (stabiler als manuelles Schreiben):
Ass-Klasse definieren + Hilfsfunktionenword()/rect(), am Endewrite(). - Harte Regeln, Vorlagen, Fallstricke siehe
ass-render-playbook(ZeitformatH:MM:SS.cc, Style-Farbwerte ohne&am Ende,fontsdirrelativer Pfad usw.).
⑥ Rendern
- Arbeitsverzeichnis = Ausgabeverzeichnis; ASS mit ASCII-Dateiname; Schriftartenverzeichnis relativ:
cd "字幕\输出\S4S6_30s"
& $ff -v error -y -i _base_30s.mp4 -vf "ass=_s4.ass:fontsdir=fonts" `
-c:v libx264 -preset medium -crf 16 -pix_fmt yuv420p -movflags +faststart S4_30s.mp4
- Transparente Überlagerung (für Nachbearbeitung):
-f lavfi -i "[email protected]:s=2560x1080:r=30,format=rgba" -vf "ass=x.ass:alpha=1"+ VP9yuva420p(Details siehe ass-render-playbook).
⑦ Abnahmeprüfliste
-
ffprobe-Dauer stimmt mit Design überein (5.000 / 30.000 / 154.6) - Einzelbild extrahiert: mindestens 1 Frame pro Textzeile, sicherstellen, dass der Text tatsächlich erscheint, Position korrekt, keine Zeichensalat
- Benutzer wünscht kein Chinesisch → 2–3 Frames extrahieren, um nur Englisch/Japanisch zu bestätigen
- Gesicht/Körper der Person nicht verdeckt (besonders bei Nahaufnahmen prüfen)
- Letzte Zeile vor Ende ausblenden (z. B. vor 29.86s), keine Restbuchstaben
-
关键帧.jpgerstellen (2×2 oder 2×3, jede Zelle 1280×540, mit Beschriftung) für Benutzeransicht - Dateiname lesbar + Erklärungs-MD zusammen ausliefern
3. Aufgabentyp → Auslieferungsgegenstand
| Aufgabe | Auslieferung |
|---|---|
| Statisches Einzelbildkonzept | N 2560×1080 jpg + 总览.jpg + Erklärungs-MD |
| 5s-Demo | 1–3 5s mp4 + Vergleichsvideo + Keyframe-Tabelle |
| 30s-Demo | 1–2 30s mp4 (900 Frames) + Vergleichsversion + Keyframe-Tabelle + Erklärungs-MD |
| Paarweise Auslieferung (häufig) | Pro Stil 2 Videos: X_mitHintergrund_30s.mp4 (H.264 eingebrannt) + X_nurUntertitel_transparent_30s.webm (VP9 alpha); N Stile × 2 Videos, plus nurUntertitel_transparent_Vorschau.jpg (Schachbrett-Kompositionsvorschau) |
| Gesamtes Video | Untertitel ASS + eingebranntes mp4 / transparentes webm + Erklärung |
| Farbkorrektur | Farbkorrigiertes mp4 + Vergleichsframes + Parametererklärung / LUT |
Transparente Version rendern (gleiches ASS wie Version mit Hintergrund, Frame-für-Frame identisch):
& $ff -v error -y -f lavfi -i "[email protected]:s=2560x1080:r=30,format=rgba" ` -vf "ass=_s4.ass:alpha=1:fontsdir=fonts" -t 30 -c:v libvpx-vp9 -pix_fmt yuva420p ` -b:v 0 -crf 30 -row-mt 1 -auto-alt-ref 0 -metadata:s:v:0 alpha_mode=1 OUT.webmAlpha prüfen:
ffmpeg -c:v libvpx-vp9 -ss 12.4 -i OUT.webm -frames:v 1 -pix_fmt rgba f.png, PIL prüft alpha min=0 / max=255, Abdeckung>0; Frame-Extraktion muss explizit-c:v libvpx-vp9verwenden, sonst geht Alpha verloren und wird zu 255.
4. Parallelverarbeitung (Unteragenten-Vereinbarung)
Standardvorgehen, wenn der Benutzer „Unteragenten separat erledigen lassen" sagt:
- Hauptagent bereitet gemeinsames Basisvideo (zugeschnitten, einheitlich abgedunkelt) und
fonts/-Kopie, Cue-Tabelle (relative Zeit) vor; - Jeder Stil ein Unteragent, mit festen Vorgaben im Prompt: Eingabepfad, Ausgabedateiname (
S4_30s.mp4usw.), ASS-Hard-Regeln, Zeitachsentabelle, Abnahmeanforderungen; - Jeder Unteragent schreibt nur seine eigene Präfix-Datei, überschreibt keine anderen;
- Hauptagent sammelt alles ein, erstellt Vergleichsvideo/Keyframe-Tabelle/Erklärung und führt die einheitliche Abnahme-Frame-Extraktion durch. Erfahrungswert: Ein einzelner 30s-Stil (2560×1080, 8 Zeilen, ca. 40–60 Dialoge) dauert vom Design bis zum fertigen Video etwa 10–20 Minuten; zwei parallele Unteragenten ≈ Zeit des langsamsten.