Remotion Video

iart-ai/motion-design-skills/skills/remotion-video

作者 iart-ai3c129f769d90無授權條款58 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫3 個月前更新

This skill should be used when the user asks to "make a video with Remotion", "create a programmatic/data-driven video in React", "render an MP4/GIF from code", "animate with useCurrentFrame/interpolate/spring", "sync video to audio/beats", or "render a templated video per record headlessly". Covers building React compositions and rendering them via CLI or @remotion/renderer.

AI 產生的概覽

使用 Remotion 在 React 中打造程式化、逐格驅動的影片,並渲染成 MP4、GIF 或 WebM。

功能
引導建立 Remotion React 合成,運用 useCurrentFrame、interpolate、spring、Sequence 與 Series 等逐格動畫基本元件,並涵蓋音訊與節拍同步。內容包括以 zod 型別化 props 註冊合成、透過 calculateMetadata 計算依資料而定的時長,以及透過 Remotion CLI 或 @remotion/renderer 進行無介面渲染。也說明先渲染精確格數的靜態畫格供檢查、再編碼最終影片的驗證流程。
適用情境
適用於需要由程式碼產生影片的情境,例如社群短片、標題卡、解說影片,或依每筆紀錄、每列資料批次渲染的範本化影片。也適合需要版本控管、程式碼審查與無圖形介面 CI 渲染的動態圖像。
執行需求
需要已安裝 Remotion 的 React/Node 專案,透過 npx remotion 或 @remotion/renderer 套件執行;使用 zod 定義型別化 props;音訊與字型等靜態資源透過 staticFile 提供。渲染以無介面方式執行,不需要圖形介面。文件提到 scripts/ 下打包的輔助指令碼用於產生聯絡表與檢測 MP4,但技能資料夾中並未包含這些指令碼檔案。

Remotion (Programmatic Video)

Build real MP4/GIF/WebM videos in React. Every frame is a pure function of useCurrentFrame(), so output is deterministic, scrubbable, diffable, and renderable in CI. The code-first alternative to After Effects for templated and data-driven motion graphics.

When to use

  • Render MP4/GIF/WebM from code (social clips, title cards, explainers).
  • Templated/data-driven videos: one composition, many outputs from props (per-user, per-record, per-row of a CSV/DB).
  • Motion graphics that must be versioned, code-reviewed, and rendered in CI without a GUI.
  • Programmatic audio sync, charts that animate from data, or embedding shaders/Three.js into video.

Core techniques

Frame-driven animation

Animation is derived from the current frame, never from setState or requestAnimationFrame. interpolate maps an input range to an output range; spring produces physically natural motion.

jsx
import {useCurrentFrame, useVideoConfig, interpolate, spring} from 'remotion';
export const Title = () => {  const frame = useCurrentFrame();  const {fps} = useVideoConfig();
  // Fade in over frames 0-30, then stay (clamp prevents over/undershoot).  const opacity = interpolate(frame, [0, 30], [0, 1], {    extrapolateLeft: 'clamp',    extrapolateRight: 'clamp',  });
  // Spring entrance; divide by spring duration is unnecessary — drive transforms directly.  const scale = spring({frame, fps, config: {damping: 200, mass: 1, stiffness: 100}});
  return <h1 style={{opacity, transform: `scale(${scale})`}}>Hello</h1>;};

Always clamp interpolate unless an intentional overshoot is desired — by default it extrapolates linearly past the range, which produces opacity > 1 or negative values.

Scheduling: Sequence and Series

<Sequence> shifts time: children see frame reset to 0 at the sequence's from. Use it to place clips on a timeline. <Series> lays out back-to-back segments without manual offset math.

jsx
import {Sequence, Series, AbsoluteFill} from 'remotion';
export const Timeline = () => (  <AbsoluteFill style={{backgroundColor: 'black'}}>    <Sequence from={0} durationInFrames={60}><Intro /></Sequence>    <Sequence from={60} durationInFrames={90}><Body /></Sequence>
    {/* Series auto-sequences; offset overlaps the previous segment for crossfades */}    <Series>      <Series.Sequence durationInFrames={60}><ShotA /></Series.Sequence>      <Series.Sequence durationInFrames={60} offset={-15}><ShotB /></Series.Sequence>    </Series>  </AbsoluteFill>);

Composition registration + parametric props

The <Composition> declares id, size, fps, duration, and defaultProps. A zod schema makes props type-safe and editable in the Studio sidebar.

jsx
import {Composition} from 'remotion';import {z} from 'zod';
export const schema = z.object({  title: z.string(),  accent: z.string(),  fps: z.number().default(30),});
export const Root = () => (  <Composition    id="Promo"    component={Promo}    durationInFrames={150}    fps={30}    width={1080}    height={1920}    schema={schema}    defaultProps={{title: 'Launch', accent: '#5b8cff', fps: 30}}  />);

To make duration data-dependent, use calculateMetadata on the Composition to compute durationInFrames from props (e.g. number of rows × frames per row) before render.

Audio and beat sync

jsx
import {Audio, staticFile, useCurrentFrame, useVideoConfig} from 'remotion';
const BEATS_SEC = [0.5, 1.0, 1.5, 2.0]; // detected offlineexport const Music = ({children}) => {  const frame = useCurrentFrame();  const {fps} = useVideoConfig();  const t = frame / fps;  const onBeat = BEATS_SEC.some((b) => Math.abs(t - b) < 1 / fps);  return (    <>      <Audio src={staticFile('track.mp3')} />      <div style={{transform: `scale(${onBeat ? 1.06 : 1})`}}>{children}</div>    </>  );};

Detect beats offline (e.g. with web-audio-beat-detector or aubio) and bake the timestamps into props — never analyze audio at render time, since headless rendering has no realtime audio clock.

Rendering

Preview in the browser-based Studio; render headlessly via CLI or the programmatic API.

bash
npx remotion studio                                  # interactive previewnpx remotion render Promo out/promo.mp4 \  --props='{"title":"Launch","accent":"#f43"}'        # pass parametric propsnpx remotion render Promo out.gif --codec=gif         # GIF output

For batch/data-driven pipelines, render in Node with @remotion/renderer (bundle once, render many) — see the reference file.

Deliver & verify (rendered stills → MP4)

Packaged helper (scripts/): tile your stills with scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png, then assert the encode with scripts/probe-mp4.sh out.mp4 [WxH] [fps]. See scripts/README.md.

Remotion is frame-deterministic by construction — every frame is a pure function of useCurrentFrame(), so you can render any exact frame headlessly with no seek harness (this is the heavy-tier counterpart to a web scene's ?t=N). Use this tier when the output must be an MP4/GIF, must carry exact numbers/text, or batches from data; for a lightweight web animation, deliver standalone HTML instead.

Output contract:

  • A Remotion project with the composition registered (<Composition> + zod schema + defaultProps), all motion frame-driven (no timers / Date.now() / Math.random()).
  • Deliverable = the rendered out/*.mp4 (plus the project, so the user can re-render with new props/data).
  • Duration data-dependent? compute it in calculateMetadata, not by hand.

Verify loop — render stills → inspect → encode. Render single frames first (cheap, no video encode), inspect them, and encode the full video only once the frames are right.

bash
# 1. Frame-exact stills at start / mid / end (PNG, headless, fast)npx remotion still Promo out/f-start.png --frame=0npx remotion still Promo out/f-mid.png   --frame=75npx remotion still Promo out/f-end.png   --frame=149   # last frame = durationInFrames - 1#    render with the SAME props you'll ship, not just defaultProps:#    npx remotion still Promo out/f-mid.png --frame=75 --props='{"title":"Launch"}'
# 2. Inspect each PNG — fidelity (matches brief; numbers/text correct) AND#    artifacts (text overflow, off-canvas, clipped safe-area, missing font, wrong data binding).
# 3. Only after the stills check out, encode the video:npx remotion render Promo out/promo.mp4 --props='{"title":"Launch"}'
  • Use npx remotion compositions to read each composition's durationInFrames/fps and pick the end frame.
  • Data-driven / batch: verify ONE representative props set via stills before batch-rendering all rows — catch a layout bug once instead of N times.
  • README demo GIF for free: npx remotion render Promo out/demo.gif --codec=gif produces the first-screen proof clip (Direction D).

Before you finish:

  1. npx remotion still renders cleanly at frame 0, mid, and last — no errors, no missing assets/fonts.
  2. Numbers/text are exact and inside safe areas at every checked frame.
  3. Frame-driven only — no Date.now() / Math.random() / timers (determinism holds in CI).
  4. Props are zod-typed; the shipped props render correctly (not just defaultProps).
  5. Full MP4 encoded and plays; (optional) GIF rendered for the README.

Quick reference

NeedUse
Map time → valueinterpolate(frame, [a,b], [x,y], {extrapolateRight:'clamp'})
Natural easingspring({frame, fps, config})
Place a clip at t<Sequence from durationInFrames>
Back-to-back shots<Series>
Audio<Audio src={staticFile(...)} />
Frame ↔ secondsframe / fps
Loop a valueframe % period then interpolate
Editable propszod schema on <Composition>
CI rendernpx remotion render or @remotion/renderer

Gotchas

  • Never use Math.random(), Date.now(), or animation timers — they break determinism. Use random(seed) from Remotion for stable per-frame randomness.
  • Load fonts and assets via staticFile() and wait with delayRender/continueRender, or fonts pop in mid-render.
  • Default interpolate extrapolates — clamp it.
  • useCurrentFrame inside a <Sequence> is local (starts at 0); use useVideoConfig().durationInFrames for absolute timing.

Reference files

  • references/api-and-patterns.md — interpolate options and Easing, spring config recipes, Sequence/Series scheduling, <Audio> + beat-sync, parametric defaultProps with zod + calculateMetadata, CLI flags, programmatic @remotion/renderer batch rendering, and embedding GLSL shaders / Three.js (@remotion/three).

來源與署名

來源:iart-ai/motion-design-skills位於skills/remotion-video提交3c129f7

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架