Remotion Master Guide — Programmatische Videoerstellung in React
Remotion ermöglicht die Erstellung kinematischer Videos mit reinem React-Code. Jeder Videoframe wird als deterministischer Zustand (frame) => UI behandelt, der perfekte 60 FPS ohne Ruckeln oder Frame-Drops erzeugt.
1. Architektur von Komposition & Root-Konfiguration
A. Root-Einstiegspunkt (Root.tsx)
import { Composition } from 'remotion';
import { MainExplainer } from './compositions/MainExplainer';
import { VerticalShort } from './compositions/VerticalShort';
export const RemotionRoot: React.FC = () => {
return (
<>
{/* 16:9 Landschaft Kinematischer Erklärfilm */}
<Composition
id="MainExplainer-1080p"
component={MainExplainer}
durationInFrames={30 * 32} // 32 Sekunden @ 30 FPS = 960 Frames
fps={30}
width={1920}
height={1080}
defaultProps={{
title: 'Misteri Mencairnya Puncak Es Dunia',
author: 'NARA Studio',
themeColor: '#f97316',
}}
/>
{/* 9:16 Vertikales TikTok / Reels / Shorts */}
<Composition
id="VerticalShort-60fps"
component={VerticalShort}
durationInFrames={60 * 15} // 15 Sekunden @ 60 FPS = 900 Frames
fps={60}
width={1080}
height={1920}
/>
</>
);
};
B. Dauer- & FPS-Regeln
- 16:9 YouTube / Erklärvideo: Empfehlung
30 fps(gute Balance zwischen Rendergeschwindigkeit und Bewegungsglätte) oder60 fpsfür ultra-scharfe Kinetic Typography. - Frame-Dauer: Berechne immer
durationInFrames = Math.round(seconds * fps). - Null Jitter: Verwende niemals
setIntervalodersetTimeout. Verwende immeruseCurrentFrame()unduseVideoConfig().
2. Layout- & Timeline-Primitive
AbsoluteFill
Basis für alle Ebenen einer Szene. Automatisch position: absolute; inset: 0; width: 100%; height: 100%;:
import { AbsoluteFill } from 'remotion';
export const SceneBackground: React.FC = () => {
return (
<AbsoluteFill style={{ backgroundColor: '#090812', overflow: 'hidden' }}>
{/* Visueller Inhalt */}
</AbsoluteFill>
);
};
Sequence vs. Series
Sequence: Platziert Elemente zu einer absoluten Zeit (fromunddurationInFrames). Ideal für Hintergrundmusik, Wasserzeichen, HUD-Overlays oder überlappende Elemente.Series: Ordnet Szenen automatisch sequentiell an, ohne manuelle Frame-Offset-Berechnung.
import { Series, Sequence, Audio, staticFile } from 'remotion';
export const VideoStory: React.FC = () => {
return (
<AbsoluteFill>
{/* Hintergrundmusik während des gesamten Videos */}
<Audio src={staticFile('audio/ambient_score.mp3')} volume={0.35} />
{/* Automatische Szenenreihenfolge */}
<Series>
<Series.Sequence durationInFrames={120}>
<HookScene />
</Series.Sequence>
<Series.Sequence durationInFrames={180}>
<ProblemScene />
</Series.Sequence>
<Series.Sequence durationInFrames={240}>
<SolutionScene />
</Series.Sequence>
<Series.Sequence durationInFrames={150}>
<CallToActionScene />
</Series.Sequence>
</Series>
</AbsoluteFill>
);
};
3. Animationsphysik: spring() & interpolate()
A. Natürliche Federformel (spring())
Verwende spring(), um echte physikalische Bewegungen zu erzeugen (vermeidet den steifen "PowerPoint"-Look):
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 1. Knackiges Erscheinen (Text/Abzeichen erscheint ruckartig)
const popScale = spring({
frame,
fps,
config: { damping: 10, mass: 0.4, stiffness: 180 },
});
// 2. Sanftes Gleiten (Kamera gleitet geschmeidig)
const smoothSlide = spring({
frame,
fps,
config: { damping: 20, mass: 1.2, stiffness: 60 },
});
// 3. Hüpfender Fall (Symbole/Partikel fallen und federn)
const bounce = spring({
frame: frame - 10, // 10 Frames Verzögerung
fps,
config: { damping: 8, mass: 0.6, stiffness: 140 },
});
B. Sanfte Werte-Zuordnung (interpolate())
import { interpolate, Easing } from 'remotion';
// Alpha- & Rotationsübergang mit Bezier-Easing
const opacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: 'clamp',
});
const rotateY = interpolate(frame, [0, 60], [-45, 0], {
easing: Easing.bezier(0.16, 1, 0.3, 1),
extrapolateRight: 'clamp',
});
4. Kinetic Typography & Voiceover-Synchronisation
A. Gestaffelte Wort-Enthüllung (Text erscheint Wort für Wort)
import React from 'react';
import { useCurrentFrame, useVideoConfig, spring, interpolate } from 'remotion';
interface KineticTextProps {
sentence: string;
startFrame?: number;
wordDelay?: number;
}
export const KineticText: React.FC<KineticTextProps> = ({
sentence,
startFrame = 0,
wordDelay = 4, // 4 Frames Abstand zwischen Wörtern
}) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const words = sentence.split(' ');
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px', justifyContent: 'center' }}>
{words.map((word, idx) => {
const wordStart = startFrame + idx * wordDelay;
const progress = spring({
frame: frame - wordStart,
fps,
config: { damping: 12, mass: 0.4, stiffness: 160 },
});
const translateY = interpolate(progress, [0, 1], [40, 0]);
const opacity = interpolate(progress, [0, 1], [0, 1]);
return (
<span
key={idx}
style={{
display: 'inline-block',
transform: `translateY(${translateY}px)`,
opacity,
fontSize: '48px',
fontWeight: 800,
color: idx === 0 ? '#f97316' : '#ffffff',
letterSpacing: '-1px',
fontFamily: "'JetBrains Mono', sans-serif",
}}
>
{word}
</span>
);
})}
</div>
);
};
B. Voiceover- & SFX-Synchronisation
- Lege Audiodateien im Ordner
public/audio/ab. - Verwende
staticFile('audio/file.mp3'). - Erstelle Audio-Fade-Ins/Fade-Outs mit der
volume-Eigenschaft:
<Audio
src={staticFile('audio/naskah_vo.mp3')}
volume={(f) =>
interpolate(f, [0, 15, 880, 900], [0, 1, 1, 0], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
})
}
/>
5. Asynchrone Assets & Vorladen (delayRender)
Wenn ein Video benutzerdefinierte Schriftarten, externe Bilder oder API-Daten lädt, MUSS Remotion mitgeteilt werden, dass keine leeren Frames gerendert werden sollen:
import { delayRender, continueRender } from 'remotion';
import { useEffect, useState } from 'react';
export const DynamicScene: React.FC = () => {
const [handle] = useState(() => delayRender('Schriftart & Asset laden'));
useEffect(() => {
document.fonts.ready.then(() => {
continueRender(handle);
});
}, [handle]);
return <AbsoluteFill>...</AbsoluteFill>;
};
6. Vorlage & Rezepte für Motion Graphics NARA
8-stufige kinematische Formel (Anti-PPT)
- Szene 1: Cold Hook (00-03s) $ ightarrow$ Mysteriöse Visuals + große kinetische Typografie.
- Szene 2: Problem benannt (04-07s) $ ightarrow$ Visuals: einstürzendes Eis / glühende rote Grafik.
- Szene 3: Deep Dive Daten (08-12s) $
ightarrow$ Statistische Zahlen zählen nach oben (
Math.floor). - Szene 4: Dynamischer Maßstabswechsel (13-16s) $ ightarrow$ Wechsel von Makro- zu Mikro-Maßstab.
- Szene 5: Menschliche Auswirkungen (17-20s) $ ightarrow$ Cartoon-Figur reagiert auf der Leinwand.
- Szene 6: Lösungsenthüllung (21-25s) $ ightarrow$ Visuals wechseln zu hellgrün/orange.
- Szene 7: Handlungsschritte (26-29s) $ ightarrow$ 3 Kartenpunkte schweben in 3D.
- Szene 8: Höhepunkt & CTA (30-32s) $ ightarrow$ Studio-Logo pulsiert + Audio-Whoosh-Einsatz.
7. Ausführung des Render-CLI & Hardwarebeschleunigung
A. Einzelnes Video rendern (1080p 60fps)
npx remotion render src/remotion/index.ts MainExplainer-1080p out/output.mp4 --gl=angle
B. Schnelles Rendern mit hohem Parallelitätsgrad
npx remotion render src/remotion/index.ts MainExplainer-1080p out/output.mp4 --concurrency=8 --gl=angle --jpeg-quality=90
C. Wichtige Render-Flags
--gl=angle: Nutzt GPU-Beschleunigung über DirectX unter Windows (deutlich schneller als Software-Rasterizer).--gl=swiftshader: Software-Fallback, wenn keine GPU im Container/CI verfügbar ist.--concurrency=N: Anzahl der CPU-Kerne, die für paralleles Rendern verwendet werden.--muted: Rendert ohne Audiostream, wenn nur das Bild benötigt wird.--props='{"title":"Baru"}': Übergibt dynamische Parameter über die JSON-Befehlszeile.
8. Fehlerbehebungsleitfaden
- Schwarzer Bildschirm / Bilder werden nicht angezeigt: Stelle sicher, dass die Assets im Ordner
public/liegen und mitstaticFile('dateiname')aufgerufen werden. - Video hängt beim Rendern fest: Prüfe auf Endlosschleifen in
useMemooder React-Komponenten, diedelayRendernicht schließen. - Audio nicht synchron: Stelle sicher, dass der
fps-Wert der Komposition exakt mit der Sekundenberechnung des Voiceovers übereinstimmt (seconds = frames / fps).