Video 100 % mit Code (Remotion + lokales Audio)
Arbeitsablauf (Reihenfolge nicht ändern)
- Geschichte zuerst (HyperFrames-Methode
story.md): die einzige Sache, 3 Handlungsstränge, Hook in den ersten 2 Sekunden, Beats mit Prozentangaben, generierte Video-„Tells“ verboten (alles gleicht sich ein, grundloses Schweben, Karten in einer Reihe, schwebendes Logo).SCRIPT.mdmit Timecodes schreiben. - Stimmen → echte Dauern →
timeline.json(Szenen, Start jeder Zeile, Ereignisse, Musikabschnitte). Audio und Video lesen dasselbe JSON. - Audio-Master (Musik + SFX + Stimmen mit Ducking, −15.5 LUFS, Spitze ≤ −1 dBTP).
- Szenen in Remotion, eine Komposition
Filmmit<Sequence>pro Szene; Kontrollbilder (Kontaktabzug) vor dem Rendern prüfen. - Render pro Szene (
--frames=a-b --muted) → concat → mux mit ffmpeg → QC mit extrahierten Einzelbildern.
Engine
npx create-video@latest --yes --blank --no-tailwind <dir>;npx remotion add @remotion/transitions @remotion/media @remotion/effects @remotion/noise @remotion/paths @remotion/shapes @remotion/motion-blur @remotion/fonts.- Sandbox ohne GPU: in
remotion.config.ts→Config.setBrowserExecutable(<chrome-headless-shell>),Config.setChromiumOpenGlRenderer("swangle"),setConcurrency(2),setCrf(18),setPixelFormat("yuv420p"). - Schriftarten: Pakete
@fontsource[-variable]/*(npm funktioniert; Google Fonts nicht). Warten aufdocument.fonts.load()mitdelayRendervor dem Erfassen (Glyphen áéíóúñ¿¡). - Remotion-Regeln: Alles leitet sich von
useCurrentFrame()ab;interpolatemit clamp;random(seed)von Remotion; kein CSStransition/animation,Math.random,Date, Timer,useFrame. - Gemessene Kosten (2 CPU, 1080p): leere Szene ≈0.1 s/f; 2000 Canvas-Sprites ≈0.7 s/f;
filter: blur()Vollbild ≈2.5 s/f. Partikel: Closed-Form (Position = f(seed, i, t)), vorverwischte radiale Sprites,globalCompositeOperation: "lighter". - Ein 3-minütiger Kurzfilm (5400 Frames, 1080×1920) dauerte ~1h30 auf 2 CPU. Bundle speichern (
npx remotion bundle) und daraus rendern.
Wiederverwendbares Kit (nicht in diesem Repository enthalten; dient als Baukastenliste)
anim.ts (Easings pro Rolle, geschlossener Spring, keyedState, Blinzeln, Drift), Camera2D.tsx (Ebenen mit Parallaxe/Dolly), Particles.tsx (Regen, Glühwürmchen, Staub, Sterne, Körnung), City.tsx (neon-prozedurale Stadt + Spiegelungen), Text.tsx (kinetisch, Neon, Untertitel Wort für Wort, variabler Titel), Post.tsx (Vignette, Blitz, Letterbox, Lichtstrahlen), character/Mia.tsx (Rig: Pose + Ausdruck + Viseme A–H/X + Blinzeln + Atmen + Randlicht + Requisit), character/Lucero.tsx, Flat.tsx (flache Welt mit Bleistift-Look und Boil), ChatScreen.tsx, lipsync.ts. Skripte in tools/: voice.py, make_voices.py, asr.py, make_timeline.py, make_audio.py, render_all.sh, assemble.sh, sheet.py.
Figuren
- Rig = numerische Parameter (Pose, Ausdruck, Visem) frame-weise mischbar; Ausdrucks-Voreinstellungen; Übergänge mit
keyedState(Antizipation → Aktion → Ausschwingen). Kopf führt, Körper folgt; Blinzeln alle 2–5 s mit Seed; nie alles gleichzeitig mit derselben Kurve bewegen. - Lippen-Sync: Rhubarb
-r phonetic -f jsonüber WAV 22 kHz mono 16 bit → Cues A–H/X → Mundparameter zwischen Cues mischen (Blend 50 ms). Öffnungsintensität ×0.7 für Flüstern. - Charakterblatt (Ausdrücke, Viseme, Posen) als Still VOR dem Animieren.
Stimme (Spanisch, lokal)
- Kokoro-82M ONNX (
kokoro-onnx, Stimmenef_dora,em_alex,em_santa, Sprachees-419) und Piper (piper-tts,es_MX-claude-high,es_AR-daniela-high). Modelle in GitHub Releases (thewh1teagle/kokoro-onnx, k2-fsa/sherpa-onnx). - Kinder: +4…+6 Halbtöne mit
rubberband -p N -F(Formanten). Tiefe: −4. „Stimme aus vielen gemacht“: Schicht −2 st (26 %) + Schicht +0.3 st verzögert 12 ms (18 %) + großer Hall. - Immer mit ASR überprüfen (Parakeet-TDT 0.6B v3 via sherpa-onnx ≥ 2.0): WER gegen den Text; Satz neu generieren oder umschreiben, wenn > 5 %. VOR Effekten überprüfen (Hall verwirrt den Spracherkenner des ASR). Die Wort-Zeitstempel des ASR speisen die Untertitel.
- Wenn der Benutzer seine eigene Stimme hat (z. B. ElevenLabs), wird das WAV jeder Zeile ersetzt und Cues/Timeline neu generiert, ohne die Szenen zu berühren.
Musik und SFX
- MIDI mit
pretty_midinach Abschnitten komponieren (bpm, Progression, GM-Instrumente) →fluidsynth -ni -g 0.6 -r 48000 -F out.wav MuseScore_General_Full.sf3 in.mid→ pedalboard (HPF, Kompressor, Hall) → pyloudnorm. - Visuelle Synchronität = gleiche Beat-Arithmetik (Frames pro Beat = fps·60/bpm, jeden Beat ab seinem Index berechnen).
- SFX mit Ursache auf dem Bildschirm; Spitze 1 Frame nach dem Bild setzen; Aufnahmen rotieren; mit numpy synthetisieren, was nicht existiert (Brummen, Regen, Bleistift, Schimmer, Sub-Impact).
- Mischung: Stimme −20 dBFS RMS, Musik −8 dB unter der Stimme (Ducking 120 ms / 700 ms), SFX −4 dB, Master −15.5 LUFS, Spitze 0.6. Mit einem Spektrogramm (
ffmpeg showspectrumpic) prüfen, dass kein Bett (Regen) die Stimme überdeckt.
Regie (aus gelesenen Skills: Remotion, HyperFrames, iart-ai motion/kinetic/webgl, nolanx, anatomy, isometric-ops, taste-skill)
- Eine Bewegung pro Beat; Ankünfte mit langem Auslauf (
bezier(0.16,1,0.3,1)), Ausgänge 40–50 % kürzer; KamerainOut; Titel bleiben ruhig, sobald sie landen; 3–5 Übergangsarten mit Ursache; im schnellsten Frame schneiden. - Parallaxe: Hintergrund 0.1–0.3×, Mitte 0.5–0.7×, Vordergrund 1–1.5× mit Unschärfe. Drohnenaufnahme = Stapel verschachtelter Ebenen mit logarithmischer Skalierung (Fenster → Fassade → Block → Karte → Wolken → Planet).
- Isometrisch: eine einzige Projektion; flache Schatten 15–30 %; oben heller.
- Typografie: maximal 2 Schriftfamilien; Titel 4–9 % der Höhe; Buchstaben-Stagger 20–40 ms, Wörter 40–70 ms; Variable Fonts für Gewicht/Breite.
- Vertikal: Schlüsselinhalte in den mittleren 80 %; Untertitel über dem unteren Sicherheitsbereich (≥ 110 px); Text ≥ 44 px; Untertitel Wort für Wort, damit sie ohne Ton verstanden werden.