Loading...
Loading...
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.
npx skill4agent add iart-ai/motion-design-skills remotion-videouseCurrentFrame()setStaterequestAnimationFrameinterpolatespringimport {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>;
};interpolate<Sequence>framefrom<Series>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>defaultPropsimport {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}}
/>
);calculateMetadatadurationInFramesimport {Audio, staticFile, useCurrentFrame, useVideoConfig} from 'remotion';
const BEATS_SEC = [0.5, 1.0, 1.5, 2.0]; // detected offline
export 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>
</>
);
};web-audio-beat-detectornpx remotion studio # interactive preview
npx remotion render Promo out/promo.mp4 \
--props='{"title":"Launch","accent":"#f43"}' # pass parametric props
npx remotion render Promo out.gif --codec=gif # GIF output@remotion/rendererPackaged helper (): tile your stills withscripts/, then assert the encode withscripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png. Seescripts/probe-mp4.sh out.mp4 [WxH] [fps].scripts/README.md
useCurrentFrame()?t=N<Composition>schemadefaultPropsDate.now()Math.random()out/*.mp4calculateMetadata# 1. Frame-exact stills at start / mid / end (PNG, headless, fast)
npx remotion still Promo out/f-start.png --frame=0
npx remotion still Promo out/f-mid.png --frame=75
npx 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"}'npx remotion compositionsdurationInFramesfpsnpx remotion render Promo out/demo.gif --codec=gifnpx remotion stillDate.now()Math.random()defaultProps| Need | Use |
|---|---|
| Map time → value | |
| Natural easing | |
| Place a clip at t | |
| Back-to-back shots | |
| Audio | |
| Frame ↔ seconds | |
| Loop a value | |
| Editable props | zod |
| CI render | |
Math.random()Date.now()random(seed)staticFile()delayRendercontinueRenderinterpolateuseCurrentFrame<Sequence>useVideoConfig().durationInFramesreferences/api-and-patterns.mdinterpolateEasing<Audio>defaultPropscalculateMetadata@remotion/renderer@remotion/three