Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Best practices for Remotion - Video creation in React
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 253% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 117% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 102% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 147% | 0% |
Use this skills whenever you are dealing with Remotion code to obtain the domain-specific knowledge.
When in an empty folder or workspace with no existing Remotion project, scaffold one using:
bashnpx create-video@latest --yes --blank --no-tailwind my-video
Replace my-video with a suitable project name.
Animate properties using useCurrentFrame() and interpolate(). Use Easing to customize the timing of the animation.
tsximport { useCurrentFrame, Easing } from "remotion"; export const FadeIn = () => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const opacity = interpolate(frame, [0, 2 * fps], [0, 1], { extrapolateRight: "clamp", extrapolateLeft: "clamp", easing: Easing.bezier(0.16, 1, 0.3, 1), }); return <div style={{ opacity }}>Hello World!</div>; };
CSS transitions or animations are FORBIDDEN - they will not render correctly. Tailwind animation class names are FORBIDDEN - they will not render correctly.
Place assets in the public/ folder at your project root.
Use staticFile() to reference files from the public/ folder.
Add images using the <Img> component:
tsximport { Img, staticFile } from "remotion"; export const MyComposition = () => { return <Img src={staticFile("logo.png")} style={{ width: 100, height: 100 }} />; };
Add videos using the <Video> component from @remotion/media:
tsximport { Video } from "@remotion/media"; import { staticFile } from "remotion"; export const MyComposition = () => { return <Video src={staticFile("video.mp4")} style={{ opacity: 0.5 }} />; };
Add audio using the <Audio> component from @remotion/media:
tsximport { Audio } from "@remotion/media"; import { staticFile } from "remotion"; export const MyComposition = () => { return <Audio src={staticFile("audio.mp3")} />; };
Assets can be also referenced as remote URLs:
tsximport { Video } from "@remotion/media"; export const MyComposition = () => { return <Video src="https://remotion.media/video.mp4" /> };
To delay content wrap it in <Sequence> and use from. To limit the duration of an element, use durationInFrames of <Sequence>. <Sequence> by default is an absolute fill. For inline content, use layout="none".
tsximport { Sequence } from "remotion"; export const Title = () => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const opacity = interpolate(frame, [0, 2 * fps], [0, 1], { extrapolateRight: "clamp", extrapolateLeft: "clamp", easing: Easing.bezier(0.16, 1, 0.3, 1), }); return <div style={{ opacity }}>Title</div>; }; export const Subtitle = () => { return <div>Subtitle</div>; }; const Main = () => { const {fps} = useVideoConfig(); return ( <AbsoluteFill> <Sequence> <Background /> </Sequence> <Sequence from={1 * fps} durationInFrames={2 * fps} layout="none"> <Title /> </Sequence> <Sequence from={2 * fps} durationInFrames={2 * fps} layout="none"> <Subtitle /> </Sequence> </AbsoluteFill> ); }
The width, height, fps, and duration of a video is defined in src/Root.tsx:
tsximport { Composition } from "remotion"; import { MyComposition } from "./MyComposition"; export const RemotionRoot = () => { return ( <Composition id="MyComposition" component={MyComposition} durationInFrames={100} fps={30} width={1080} height={1080} /> ); };
Metadata can also be calculated dynamically:
tsximport { Composition, CalculateMetadataFunction } from "remotion"; import { MyComposition, MyCompositionProps } from "./MyComposition"; const calculateMetadata: CalculateMetadataFunction< MyCompositionProps > = async ({ props, abortSignal }) => { const data = await fetch(`https://api.example.com/video/${props.videoId}`, { signal: abortSignal, }).then((res) => res.json()); return { durationInFrames: Math.ceil(data.duration * 30), props: { ...props, videoUrl: data.url, }, width: 1080, height: 1080, }; }; export const RemotionRoot = () => { return ( <Composition id="MyComposition" component={MyComposition} fps={30} width={1080} height={1080} defaultProps={{ videoId: "abc123" }} calculateMetadata={calculateMetadata} /> ); };
Start the Remotion Studio to preview a video:
bashnpx remotion studio
You can render a single frame with the CLI to sanity-check layout, colors, or timing. Skip it for trivial edits, pure refactors, or when you already have enough confidence from Studio or prior renders.
bashnpx remotion still [composition-id] --scale=0.25 --frame=30
At 30 fps, --frame=30 is the one-second mark (--frame is zero-based).
When dealing with captions or subtitles, load the ./rules/subtitles.md file for more information.
For some video operations, such as trimming videos or detecting silence, FFmpeg should be used. Load the ./rules/ffmpeg.md file for more information.
When needing to detect and trim silent segments from video or audio files, load the ./rules/silence-detection.md file.
When needing to visualize audio (spectrum bars, waveforms, bass-reactive effects), load the ./rules/audio-visualization.md file for more information.
When needing to use sound effects, load the ./rules/sfx.md file for more information.
See rules/3d.md for 3D content in Remotion using Three.js and React Three Fiber.
See rules/audio.md for advanced audio features like trimming, volume, speed, pitch.
See rules/calculate-metadata.md for dynamically set composition duration, dimensions, and props.
See rules/compositions.md for how to define stills, folders, default props and for how to nest compositions.
Is the recommended way to load fonts in Remotion. See rules/google-fonts.md for how to load Google Fonts.
See rules/local-fonts.md for how to load local fonts.
See rules/get-audio-duration.md for getting the duration of an audio file in seconds with Mediabunny.
See rules/get-video-dimensions.md for getting the width and height of a video file with Mediabunny.
See rules/get-video-duration.md for getting the duration of a video file in seconds with Mediabunny.
See rules/gifs.md for how to display GIFs synchronized with Remotion's timeline.
See rules/images.md for sizing and positioning images, dynamic image paths, and getting image dimensions.
See rules/light-leaks.md for light leak overlay effects using @remotion/light-leaks.
See rules/lottie.md for embedding Lottie animations in Remotion.
See rules/html-in-canvas.md if you need to render HTML into a <canvas> to apply 2D or WebGL effects via <HtmlInCanvas>.
See rules/measuring-dom-nodes.md for measuring DOM element dimensions in Remotion.
See rules/measuring-text.md for measuring text dimensions, fitting text to containers, and checking overflow.
See rules/sequencing.md for more sequencing patterns - delay, trim, limit duration of items.
See rules/tailwind.md for using TailwindCSS in Remotion.
See rules/text-animations.md for typography and text animation patterns.
See rules/timing.md for advanced timing with interpolate and Bézier easing, and springs.
See rules/transitions.md for scene transition patterns.
See rules/transparent-videos.md for rendering out a video with transparency.
See rules/trimming.md for trimming patterns - cutting the beginning or end of animations.
See rules/videos.md for advanced knowledge about embedding videos - trimming, volume, speed, looping, pitch.
See rules/parameters.md for making a composition parametrizable by adding a Zod schema.
For simple maps with little flyovers, consider using static map images. For complex maps with animated routes or flyovers, load the maps rule: rules/maplibre.md
See rules/voiceover.md for adding AI-generated voiceover to Remotion compositions using ElevenLabs TTS.
Other measured skills in the registry, with their headline benchmark lift.