Panduan Master Remotion — Pembuatan Video Programmatis dalam React
Remotion memungkinkan pembuatan video sinematik dengan kode React murni. Setiap frame video diperlakukan sebagai status deterministik (frame) => UI, menghasilkan visual 60 FPS sempurna tanpa jeda atau frame drop.
1. Arsitektur Komposisi & Konfigurasi Root
A. Titik Masuk Root (Root.tsx)
import { Composition } from 'remotion';
import { MainExplainer } from './compositions/MainExplainer';
import { VerticalShort } from './compositions/VerticalShort';
export const RemotionRoot: React.FC = () => {
return (
<>
{/* 16:9 Lanskap Sinematik Explainer */}
<Composition
id="MainExplainer-1080p"
component={MainExplainer}
durationInFrames={30 * 32} // 32 detik @ 30 FPS = 960 frames
fps={30}
width={1920}
height={1080}
defaultProps={{
title: 'Misteri Mencairnya Puncak Es Dunia',
author: 'NARA Studio',
themeColor: '#f97316',
}}
/>
{/* 9:16 Vertikal TikTok / Reels / Shorts */}
<Composition
id="VerticalShort-60fps"
component={VerticalShort}
durationInFrames={60 * 15} // 15 detik @ 60 FPS = 900 frames
fps={60}
width={1080}
height={1920}
/>
</>
);
};
B. Aturan Durasi & FPS
- 16:9 YouTube / Explainer: Rekomendasi
30 fps(seimbang antara kecepatan rendering & kehalusan gerak) atau60 fpsuntuk kinetic typography ultra-crisp. - Durasi Frame: Selalu hitung
durationInFrames = Math.round(seconds * fps). - Zero Jitter: Jangan gunakan
setIntervalatausetTimeout. Selalu gunakanuseCurrentFrame()danuseVideoConfig().
2. Tata Letak & Primitif Timeline
AbsoluteFill
Dasar dari seluruh layer adegan. Otomatis position: absolute; inset: 0; width: 100%; height: 100%;:
import { AbsoluteFill } from 'remotion';
export const SceneBackground: React.FC = () => {
return (
<AbsoluteFill style={{ backgroundColor: '#090812', overflow: 'hidden' }}>
{/* Konten visual */}
</AbsoluteFill>
);
};
Sequence vs Series
Sequence: Menempatkan elemen pada waktu absolut (fromdandurationInFrames). Ideal untuk audio latar, watermark, overlay HUD, atau elemen yang saling tumpang tindih.Series: Mengurutkan adegan secara sekuensial otomatis tanpa perlu menghitung offset frame manual.
import { Series, Sequence, Audio, staticFile } from 'remotion';
export const VideoStory: React.FC = () => {
return (
<AbsoluteFill>
{/* Audio Musik Latar Sepanjang Video */}
<Audio src={staticFile('audio/ambient_score.mp3')} volume={0.35} />
{/* Urutan Adegan Otomatis */}
<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. Fisika Animasi: spring() & interpolate()
A. Formula Pegas Alami (spring())
Gunakan spring() untuk menghasilkan gerakan fisika nyata (menghilangkan kesan kaku "PowerPoint"):
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 1. Snappy Pop (Teks/Badge Muncul Menghentak)
const popScale = spring({
frame,
fps,
config: { damping: 10, mass: 0.4, stiffness: 180 },
});
// 2. Smooth Drift (Kamera Meluncur Halus)
const smoothSlide = spring({
frame,
fps,
config: { damping: 20, mass: 1.2, stiffness: 60 },
});
// 3. Bouncy Drop (Ikon/Partikel Jatuh Memantul)
const bounce = spring({
frame: frame - 10, // delay 10 frame
fps,
config: { damping: 8, mass: 0.6, stiffness: 140 },
});
B. Pemetaan Nilai Halus (interpolate())
import { interpolate, Easing } from 'remotion';
// Transisi Alpha & Rotasi dengan Easing Bezier
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 & Sinkronisasi Voiceover
A. Staggered Word Reveal (Teks Muncul Kata per Kata)
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 frame jarak antar kata
}) => {
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. Sinkronisasi Voiceover & SFX
- Tempatkan file audio di folder
public/audio/. - Gunakan
staticFile('audio/file.mp3'). - Buat transisi audio fade in/fade out menggunakan properti
volume:
<Audio
src={staticFile('audio/naskah_vo.mp3')}
volume={(f) =>
interpolate(f, [0, 15, 880, 900], [0, 1, 1, 0], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
})
}
/>
5. Aset Async & Pra-pemuatan (delayRender)
Ketika video memuat font kustom, gambar eksternal, atau data API, Remotion HARUS diberi tahu agar tidak merender frame kosong:
import { delayRender, continueRender } from 'remotion';
import { useEffect, useState } from 'react';
export const DynamicScene: React.FC = () => {
const [handle] = useState(() => delayRender('Memuat Font & Asset'));
useEffect(() => {
document.fonts.ready.then(() => {
continueRender(handle);
});
}, [handle]);
return <AbsoluteFill>...</AbsoluteFill>;
};
6. Template & Resep Motion Grafis NARA
Formula 8 Tahap Sinematik (Anti-PPT)
- Scene 1: Cold Hook (00-03s) → Visual misteri + Tipografi kinetik besar.
- Scene 2: Problem Stated (04-07s) → Visual es runtuh / grafik merah membara.
- Scene 3: Deep Dive Data (08-12s) → Angka statistik berhitung naik (
Math.floor). - Scene 4: Dynamic Scale Shift (13-16s) → Perubahan skala makro ke mikro.
- Scene 5: Human Impact (17-20s) → Karakter kartun bereaksi di canvas.
- Scene 6: Solution Revelation (21-25s) → Visual beralih ke warna hijau/oranye terang.
- Scene 7: Action Steps (26-29s) → 3 poin kartu melayang 3D.
- Scene 8: Climax & CTA (30-32s) → Logo studio pulse + audio whoosh drop.
7. Eksekusi Render CLI & Akselerasi Hardware
A. Render Video Tunggal (1080p 60fps)
npx remotion render src/remotion/index.ts MainExplainer-1080p out/output.mp4 --gl=angle
B. Render Cepat dengan Konkurensi Tinggi
npx remotion render src/remotion/index.ts MainExplainer-1080p out/output.mp4 --concurrency=8 --gl=angle --jpeg-quality=90
C. Flag Rendering Penting
--gl=angle: Menggunakan akselerasi GPU DirectX di Windows (jauh lebih cepat dari software rasterizer).--gl=swiftshader: Fallback software jika GPU tidak tersedia di container/CI.--concurrency=N: Jumlah core CPU yang digunakan untuk render paralel.--muted: Merender tanpa audio stream jika hanya butuh visual.--props='{"title":"Baru"}': Melewatkan parameter dinamis via JSON command line.
8. Panduan Pemecahan Masalah
- Layar Hitam / Gambar Tidak Muncul: Pastikan aset berada di folder
public/dan dipanggil denganstaticFile('nama_file'). - Video Macet Saat Render: Cek apakah ada infinite loop di
useMemoatau komponen React yang tidak menutupdelayRender. - Audio Out of Sync: Pastikan nilai
fpskomposisi sama persis dengan perhitungan detik voiceover (seconds = frames / fps).