Remotion-Taktsynchronisations-Videopipeline
Ziel: Zu einem gegebenen Thema und einem BGM ein 88–90 Sekunden / 16:9 / ohne Sprachausgabe / zweisprachige Untertitel (CHN/ENG) / jeder Szenenwechsel auf dem schweren Takt fertiges Video produzieren, plus drei Cover-Varianten, Veröffentlichungspaket und zu prüfende Faktenliste. Alles ist Code – Untertitel ändern bedeutet String-Änderungen, ein erneutes Rendern dauert etwa 35 Minuten.
Wann verwenden
- "Mach dieses Thema zu einem TikTok-Wissensvideo / Strategiespiel-Erklärvideo"
- "Mach mit der BGM von XY ein taktsynchrones Video"
- "Mach diesen Abschnitt aus dem Roman zu einem Video" (fiktives IP, siehe
references/fact-check.md) - Benötigt wird eine komplette Lieferung: fertiges Video + Cover + Veröffentlichungstext + Faktencheck
Wann NICHT verwenden
- Sprach-Paraphrase erforderlich (dieser Workflow ist textbasierte Erzählung ohne Sprachausgabe; für Sprachausgabe müsste zuerst eine TTS-Spur erstellt und synchronisiert werden)
- Echt-/AIGC-Material-Schnitt gewünscht (dieser Workflow verwendet reine Code-SVG-Bilder)
- Nur Text und Bilder ohne Video
〇、Stil-DNA (Zuerst lesen, alle aus der Praxis)
| Dimension | Regel | Warum |
|---|---|---|
| Seitenverhältnis | 1920×1080 / 30fps (Hochformat separate Composition) | Der Kanal ist auf 16:9 festgelegt, Daten zeigen höhere Effizienz |
| Dauer | 88–90 Sekunden (≈42 Takte) | Liegt im Testbereich "60–90s pro Episode" |
| Audio | Keine Sprachausgabe, BGM + synthetische Soundeffekte | Stilistische Anforderung; vermeidet auch TTS-Synchronisationskosten |
| Untertitel | Zweisprachig CHN/ENG in zwei Zeilen, Chinesisch ≤22 Zeichen, jede Phrase ≥2,2 Sekunden | Kanalstil (TikTok empfiehlt generell einsprachig, dies ist eine Kanalentscheidung) |
| Einstieg | Sekunde 1 = ein vollständiger Konfliktsatz + ein konkretes Objekt | 2-Sekunden-Abbruchrate ist der größte Schwachpunkt |
| Erzählung | Eine Person + ein Problem + eine Kausalkette | Vermeide "Konzeptgalerie" und "Gruppenschnitt" |
| Struktur | Haken → Titel → Regel → Falle → Gegenschlag → Rückschlag → Enthüllung → Erhebung → Abschluss | Siehe references/script-template.md |
| Rhythmus | Jede Szene ab schwerem Takt harter Schnitt; Schlüsselaktionen auf dem Takt | Taktgefühl kommt von der Musikstruktur, nicht manuell ausgerichtet |
| Bild | Dunkler Hintergrund + metallische/holzige/goldene Texturen + große Schrift + wenige Tags | Lesbarkeit bei Smartphone-Verkleinerung |
| Sicherheitszone | Szenenelemente y ≤ 850; Untertitel y≈870–1000; Kopf oben links y 50–95 | Häufigste Fehlerquelle in der Praxis |
| Ende | Muss eine screenshotfähige Liste (Merkmale) + eine Frage enthalten | Merkrate ist der größte Schwachpunkt |
| Genauigkeit | Fiktives IP muss "Abbildung ist schematisch" kennzeichnen; Fakten nach Ebenen markieren | Siehe references/fact-check.md |
一、Acht-Schritte-Workflow (Schritt für Schritt ausführen, keine Sprünge)
Schritt 1: Projektstart (Themenauswahl + Bestätigung)
- Wenn der Benutzer kein Thema angibt, zuerst 3 Kandidaten vorschlagen (jeweils mit: Ein-Satz-Kern / Haken für Sekunde 1 / Begründung für visuelle Darstellung / Merkmale / Risiken), den Benutzer auswählen lassen.
- Kandidaten müssen vor dem Vorschlag auf Existenz geprüft werden: Fiktives IP muss einen Kapitelnamen oder Eintrag haben; Wissensinhalte müssen eine Quelle haben.
- Nach Auswahl des Benutzers die rohen Materialien zum Thema besorgen (beste: Original-Textabschnitte; bei sekundären Zusammenstellungen muss die Quellenebene markiert werden, siehe Schritt 8).
Schritt 2: Spur und Takt (bestimmt alle Zeit)
# ① Spur extrahieren (mp4/mp3 ok; falls kein system-ffmpeg vorhanden, wird automatisch imageio-ffmpeg verwendet)
python scripts/extract_audio.py 输入.mp4 work/ # → work/audio.f32 + work/music.mp3
# ② Takt / schwerer Takt / Abschnitte / Tonart
python scripts/analyze_beats.py work/audio.f32 src/beats.json
# ③ Energie scannen, Fenster auswählen (kritischer Schritt)
python scripts/scan_energy.py src/beats.json work/audio.f32 --seconds 89
- Ausgabe liefert: START_BAR / END_BAR, Energie pro Takt, wie viel Prozent des Fensters in der Stille liegt.
- Setze den Wendepunkt auf den ersten schweren Takt nach der Stille – das ist die wertvollste Sekunde des gesamten Videos.
- Das Fenster sollte nicht das abschwellende Ende erfassen (das würde einen toten Schluss hinterlassen).
- Falls ein Lied bereits in der Serie verwendet wurde, bevorzuge die nicht verwendete zweite Hälfte, um Wiederholung zu vermeiden.
Schritt 3: Drehbuch schreiben (src/script.ts)
- Jede Szene deklariert
bars(wie viele Takte sie einnimmt). Die Summe aller bars muss END_BAR − START_BAR ergeben (sonst skaliertplaceScenesproportional und warnt). - Untertitel in
subs:{zh, en, at},atist der wievielte Takt innerhalb der Szene (z. B. 4.5 für einen halben Takt). Eine Phrase über 4–5 Takte ist optimal. - Soundeffekte in
cues:{id, beat, sfx, vol, impact};impact:'big'= weißer Blitz + Bildschirmbeben + Farbdispersion + Musik-Seitenkette weicht 40 Frames. - Rhythmus-Budget:
Anzahl Sätze × 2,5–3 Sekunden ≈ Gesamtdauer. 89 Sekunden sind etwa 30 Sätze.
Schritt 4: Visuelle Komponenten und Szenen (src/*/kit.tsx + src/*/scenes.tsx)
- Zuerst alle Komponenten schreiben, dann die Szenen: Ein Thema hat meist 6–10 Komponenten (Beispiel: Metallbox/Schloss/Schlüssel/Zerkleinerer/Mikrowelle/Personensilhouette/Statue/Lampe/Lotterieschein/Schalter/Dao-Münze).
- Alle Komponenten sind reines SVG, Koordinaten fest auf 1920×1080, über
translate/scalewiederverwendbar. - Szenen-Komponenten sind nur dafür verantwortlich, Komponenten nach Takt zu platzieren:
const bf = (n) => beatFrame(scene, n), Einblendung immer mit Easing wiepp(f, bf(n), 8). - Checkliste siehe
references/visual-kit.md.
Schritt 5: Projektaufbau
Ein Projekt enthält mehrere Videos: src/<episode>/{script.ts,timeline.ts,fx.tsx,kit.tsx,scenes.tsx,Main.tsx},
in src/Root.tsx eine zweite <Composition> registrieren, jede mit eigenem beats.json und music.mp3.
- Das zweite Video muss eigene Beat-Hülle haben (Shell/ImpactFlash in
fx.tsxmüssen die cueFrame des eigenen Videos verwenden, sonst verschieben sich die Einschläge). - Audio mit
<Audio startFrom={OFF}>, Inhalt insgesamt<Sequence from={-OFF}>, damit innerhalb der Szene immer "Musik-Frames" als Zeitbasis verwendet werden. - Details siehe
references/pipeline.md.
Schritt 6: Still-Frame-Prüfung (nicht rendern, wenn fehlerhaft)
node <node> node_modules/@remotion/cli/remotion-cli.js still <Comp> out/s1.png --frame=<Szenenmitte>
Jede Szene ein Standbild rendern und visuell vier Dinge prüfen:
- Überlappen Untertitel Szenenelemente? (häufigster Fehler)
- Elemente überlappen sich? (Tag auf Tag, Tag auf Grafik)
- Sicherheitszone? (Element y ≤ 850)
- Ist der Text bei Smartphone-Verkleinerung lesbar? (Chinesisch ≥24px, Haupttitel ≥120px)
Schritt 7: Video rendern und Endprüfung
node <node> node_modules/@remotion/cli/remotion-cli.js render <Comp> out/<name>.mp4 --codec=h264 --crf=18 --concurrency=6
python scripts/check_mp4.py out/<name>.mp4 # Dauer / Anzahl Tracks / Auflösung / Audio-Parameter
check_mp4.py benötigt kein ffprobe: es parst direkt die mp4-Box, prüft vide + soun zwei Spuren, korrekte Dauer, 1920×1080, AAC 48kHz.
Schritt 8: Lieferung
python scripts/make_covers.py --src out/<Ein Standbild>.png --crop x0,y0,x1,y1 \
--title Haupttitel --kicker Untertitel --sub Ein Satz --out-prefix out/Cover_XXX
Vier Liefergegenstände:
- Fertiges Video mp4 (in das Arbeitsverzeichnis kopieren, Dateiname mit Thema)
- Drei Cover-Varianten (16:9 / 3:4 / 9:16) – niemals automatischen Frame-Schnitt verwenden
- Veröffentlichungspaket (Text + Kommentar oben + Cover-Vorschlag + 24h-Entscheidungstabelle), Vorlage in
references/cover-and-publish.md - Zu prüfende Faktenliste (bei fiktivem IP obligatorisch) + Drehbuch-Storyboard (Zeitcode-Tabelle)
二、Eiserne Regeln (alle aus der Praxis)
- Der erste Frame ist kein Intro, sondern ein Haken: Ein vollständiger Konfliktsatz + ein konkretes Objekt ("Die Geisel ist in der Mikrowelle eingeschlossen, der Countdown läuft").
- Untertitel-Sicherheitszone: Szenenelemente immer auf y ≤ 850, Untertitel bei 870–1000. Bei der Still-Frame-Prüfung zuerst darauf achten.
- Ein Satz Untertitel ≤22 Zeichen, Verweildauer ≥2,2 Sekunden; Chinesischer Hauptsatz + englische Übersetzung in zwei Zeilen.
- Das Ende muss screenshotfähig sein: Eine Drei-Schritte/Drei-Signale-Liste + "Speicher es dir ab"; ein Ende, das nur Emotionen weckt, erhält keine Merker.
- Stille = Wendepunkt:
scan_energy.pygibt an, in welchem Takt die Stille liegt. Setze den stärksten Wendepunkt danach. - Große Einschläge sparsam einsetzen:
impact:'big'löst weißen Blitz + Bildschirmbeben + Farbdispersion + Musik-Rückzug aus; 5–8 Mal im gesamten Video sind genug, mehr stumpft ab. - Keine gleichmäßige Bewegung: Alle Einblendungen mit Easing (
Easing.out(cubic)), Tags mit leichter Verschiebung + Skalierung beim Ausblenden. - Schriftart: Keine "auf alten Text zugeschnittene Subset-Schriftart" verwenden (neuer Text kann Zeichen fehlen) – stattdessen systemeigenen Font-Stack
'Noto Sans SC','Microsoft YaHei'verwenden. - public/ wird komplett kopiert: Nur verwendete Soundeffekte behalten (Beispiel: 148 → 16, jedes Rendern spart 60MB).
- Remotions ETA ist am Anfang überhöht: Keine Angst vor "noch 3 Stunden"; in der Praxis stabil bei ~1,35 Frames/s, 2700 Frames ≈ 35 Minuten.
- Fiktives IP in drei Ebenen kennzeichnen: Originaltext / Leserzusammenfassung / Meine Vermutung – im Video nur den Konsens der ersten beiden Ebenen verwenden, der Rest in die Prüfliste.
- Keine festen Zahlen im Video verwenden ("Vier Tierkreiszeichen" → "Mehrere Tierkreiszeichen"), keine festen Kapitelnummern ("Kapitel 359" → "ungefähr um Kapitel 359 herum").
三、Verzeichnis-Konvention
<project>/
├── public/music.mp3 # BGM für dieses Video
├── public/music.f32(+.json) # Für Taktanalyse (löschbar)
├── public/sfx/*.wav # Nach Tonart synthetisierte Soundeffekte
├── src/beats.json # Ausgabe von analyze_beats
├── src/script.ts # Text-Tabelle (nur hier ändern für Inhaltsänderungen)
├── src/timeline.ts # Mapping Szene → schwerer Takt + OFF/TOTAL
├── src/Root.tsx # Composition registrieren
├── src/fx.tsx # Bildschirmbeben/weißer Blitz/Farbdispersion/zweisprachige Untertitel
├── src/<episode>/** # Zweites und folgende Videos: eigenes script/timeline/fx/kit/scenes/Main
├── tools/ # scripts/ dieses Skills
└── out/ # Standbilder + fertige Videos + Cover
四、Referenzdateien
references/pipeline.md—— Umgebungseinrichtung und vollständige Befehle (inkl. aller Fallstricke dieses Rechners: kein ffmpeg / scipy / npm)references/script-template.md—— Drehbuch-Strukturvorlage + Taktumrechnungstabelle + echte Zeitcodes der beiden Beispielvideosreferences/visual-kit.md—— Visuelle Komponenten-Spezifikation, Sicherheitszone, Farbgebung, häufige Überlappungsfallenreferences/sfx-and-mix.md—— Soundeffekt-Synthese (nach Tonart), Seitenkette-Rückzug, Lautstärkereferences/fact-check.md—— Prüfmethode für fiktives IP und Kennzeichnungsregeln für "Leser-Rephrasierung" (inkl. nutzbarer Bilibili-API)references/cover-and-publish.md—— Drei-Cover-Varianten-Spezifikation + Veröffentlichungspaket-Vorlage + 24h-Entscheidungexamples/十日终焉-两集.md—— Struktur, Daten und Entscheidungsprotokoll zweier echter Fälle
五、Fähigkeitsgrenzen (ehrlich zum Benutzer)
- Dieser Workflow erzeugt keine Sprachausgabe; für Voiceover muss eine separate TTS erstellt und die Untertitel neu synchronisiert werden.
- In netzwerkbeschränkten Umgebungen (viele Domains von DNS geblockt) können Details zu fiktivem IP nur aus sekundären Quellen stammen – dann muss die Prüfliste aus Schritt 8 verwendet werden, nicht fest reinschreiben.
- Rendering ist Rechenarbeit: Auf einem 4-Kern-Laptop dauert ein 89-Sekunden-1080p-Video etwa 35 Minuten; nicht "in Minuten fertig" versprechen.
- Urheberrecht: BGM aus TikTok-Videos extrahiert ist nur für eigene Referenz geeignet; bei Veröffentlichung bitte die Original-Tonquelle/Ton-Karte des Plattformanbieters verlinken.