Remotion logo

remotion

Community

Programmatic video creation using React components

$ npx docs2skills add remotion-video
SKILL.md
core-apis.md
cloud-rendering.md
rendering-guide.md
player-component.md
media-integrations.md

Remotion

Programmatic video creation using React components

What this skill does

Remotion enables you to create videos programmatically using React components and web technologies. Instead of traditional video editing software, you write React code that renders frame-by-frame to create MP4 videos, animated GIFs, or still images. This approach makes videos data-driven, allowing you to generate thousands of personalized videos, create dynamic visualizations, or build complete video editing applications.

The framework provides a timeline-based composition system where you arrange sequences of React components across frames. Each component can use familiar CSS animations, SVG graphics, Canvas APIs, or even 3D scenes with Three.js. Remotion handles the complexity of rendering these components into video frames and encoding them with FFmpeg, while providing a studio environment for preview and debugging.

What sets Remotion apart is its ability to make videos reactive to data. You can fetch APIs, process user input, adjust video duration based on content length, or generate entirely different video layouts based on parameters. This makes it ideal for creating video applications like social media content generators, automated marketing videos, data visualizations, or personalized video experiences at scale.

Prerequisites

  • Node.js 16+ or Bun 1.0.3+
  • Modern browser for Remotion Studio
  • FFmpeg (auto-installed by Remotion if missing)
  • For cloud rendering: AWS account (Lambda) or Google Cloud (Cloud Run)
  • For React apps: React 17+ and compatible bundler

Quick start

# Create new project
npm create video@latest

# Start Remotion Studio
npm run dev

# Render video
npm run build

Basic composition:

import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion';

export const MyVideo = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  
  const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: 'clamp' });
  
  return (
    <div style={{
      flex: 1,
      backgroundColor: '#000',
      justifyContent: 'center',
      alignItems: 'center',
      display: 'flex',
      fontSize: 100,
      color: 'white',
      opacity
    }}>
      Hello World! Frame: {frame}
    </div>
  );
};

// Root.tsx - Register compositions
import { Composition } from 'remotion';
import { MyVideo } from './MyVideo';

export const RemotionRoot = () => {
  return (
    <Composition
      id="MyVideo"
      component={MyVideo}
      durationInFrames={90}
      fps={30}
      width={1920}
      height={1080}
    />
  );
};

Core concepts

Frame-based animation: Videos are sequences of frames, and animations work by changing properties over time using useCurrentFrame(). Think of each frame as a React render where the frame number drives the animation state.

Compositions: A composition combines a React component with video metadata (duration, dimensions, framerate). Each composition becomes a renderable video. You can have multiple compositions in one project for different video variants.

Sequences: Use <Sequence> to control the timing and layering of components. Sequences can overlap, have delays, and be nested to create complex timelines without manually calculating frame ranges.

Interpolation: The interpolate() function maps frame ranges to value ranges, enabling smooth transitions. Combined with easing functions, it replaces traditional keyframe animation with mathematical expressions.

Server-side rendering: Unlike browser-based video, Remotion renders server-side using headless Chromium and FFmpeg. This enables high-quality output, long videos, and scalable cloud rendering without browser limitations.

Key API surface

For complete reference for core APIs, read the core-apis.md file in this skill directory.

APIPurpose
useCurrentFrame()Get current frame number (0-based)
useVideoConfig()Get composition metadata (fps, duration, dimensions)
interpolate(input, inputRange, outputRange, options?)Map frame ranges to value ranges
spring(fps, frame, config?)Create spring-based animations
<Sequence from={30} durationInFrames={60}>Time-shift and limit component visibility
<AbsoluteFill>Create full-screen positioned container
<Video src="video.mp4" />Embed existing videos
<Audio src="audio.mp3" />Add audio tracks
<Img src="image.jpg" />Display images with Remotion-specific loading
staticFile('public/file.txt')Reference files in public directory
<Composition id="MyComp" component={Component} />Register renderable compositions
continueRender(delayHandle)Resume rendering after async operations
delayRender()Pause rendering for data fetching
random(seed?)Deterministic random numbers for consistent renders
getRemotionEnvironment()Detect if running in studio, rendering, or player

Common patterns

Fade transitions:

const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: 'clamp' });
return <div style={{ opacity }}>Content</div>;

Sequential animations:

<>
  <Sequence from={0} durationInFrames={60}>
    <FirstScene />
  </Sequence>
  <Sequence from={45} durationInFrames={60}>
    <SecondScene />
  </Sequence>
</>

Data-driven duration:

export const MyComposition = ({ items }: { items: string[] }) => {
  return (
    <Composition
      id="DataVideo"
      component={MyVideo}
      durationInFrames={items.length * 30} // 30 frames per item
      fps={30}
      width={1920}
      height={1080}
      defaultProps={{ items }}
    />
  );
};

Async data fetching:

const [data, setData] = useState(null);
const [handle] = useState(() => delayRender());

useEffect(() => {
  fetch('/api/data')
    .then(res => res.json())
    .then(data => {
      setData(data);
      continueRender(handle);
    });
}, [handle]);

Looping animations:

const rotation = interpolate(
  frame % 60, // Loop every 60 frames
  [0, 60],
  [0, 360]
);
return <div style={{ transform: `rotate(${rotation}deg)` }}>Content</div>;

Configuration

Essential config options in remotion.config.ts:

import { Config } from '@remotion/cli/config';

// Core settings
Config.setVideoImageFormat('jpeg'); // or 'png' for transparency
Config.setPixelFormat('yuv420p'); // Video pixel format
Config.setCodec('h264'); // Video codec
Config.setCrf(18); // Quality (lower = better, 0-51)
Config.setAudioCodec('aac'); // Audio codec

// Performance
Config.setConcurrency(4); // Parallel rendering threads
Config.setFrameRange([0, 100]); // Render subset of frames
Config.setEveryNthFrame(2); // Skip frames (for previews)

// Assets and bundling
Config.setPublicDir('./public'); // Static assets directory
Config.setEntryPoint('./src/index.tsx'); // Main file
Config.overrideWebpackConfig(config => config); // Custom webpack
Config.setBundlingTimeout(120); // Bundling timeout seconds

// Cloud rendering
Config.setChromiumExecutablePath('/path/to/chrome'); // Custom Chrome
Config.setFfmpegExecutablePath('/path/to/ffmpeg'); // Custom FFmpeg

Best practices

Always use useCurrentFrame() for animations: Never use CSS transitions, setTimeout, or other time-based APIs that aren't frame-driven, as they'll cause flickering during rendering.

Optimize heavy computations: Use useMemo() with frame dependencies to avoid recalculating expensive operations every render:

const complexValue = useMemo(() => 
  heavyComputation(frame), [frame]
);

Handle async operations properly: Always use delayRender() and continueRender() for data fetching, never render incomplete states.

Design for different aspect ratios: Use AbsoluteFill and responsive layouts rather than fixed positioning to support multiple output formats.

Use sequences for complex timing: Instead of calculating frame ranges manually, compose scenes using <Sequence> components with natural durations.

Optimize bundle size: Keep components lightweight and use dynamic imports for heavy libraries that aren't needed in all compositions.

Test with different frame rates: Ensure animations work smoothly at both 30fps and 60fps by using fps-aware calculations.

Use deterministic data: For consistent renders, use random(seed) instead of Math.random() and avoid timestamps or non-deterministic data sources.

Gotchas and common mistakes

Frame 0 is the first frame: Videos start at frame 0, not 1. The last frame is durationInFrames - 1.

CSS animations don't work during rendering: CSS transitions, animations, and setTimeout() are ignored during headless rendering. Only frame-driven animations work.

Public folder path confusion: Use staticFile() to reference assets in the public folder, not relative paths or imports.

Memory leaks with delayRender: Every delayRender() call must have a matching continueRender() call, or rendering will hang forever.

Aspect ratio math errors: When using interpolate() with different aspect ratios, remember that coordinate systems might need adjustment.

Audio sync issues: Audio files must be properly encoded. Some formats cause sync drift. Use high-quality AAC or WAV files.

Flickering from unloaded assets: Images and videos must be fully loaded before rendering. Use <Img> and <Video> components, not HTML tags.

Hot reload breaking state: The Remotion Studio hot-reloads, which can reset component state. Design components to handle remounting gracefully.

Lambda timeout limits: AWS Lambda functions timeout at 15 minutes. Very long videos need chunked rendering or alternative deployment.

Node.js vs browser differences: Some Node.js APIs aren't available in the Studio (browser environment). Use getRemotionEnvironment() to detect context.

Version mismatches: All @remotion/* packages must use the exact same version. Remove ^ from package.json versions to prevent conflicts.

Encoding inconsistencies: Different codecs and pixel formats have compatibility issues. Test your output format with your target platform early.

For detailed rendering guide including CLI commands and encoding options, read the rendering-guide.md file in this skill directory.

For embedding interactive videos in React apps, read the player-component.md file in this skill directory.

For scalable cloud rendering setup and configuration, read the cloud-rendering.md file in this skill directory.

For working with audio, video, and external media libraries, read the media-integrations.md file in this skill directory.