Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add digitalsamba/claude-code-video-toolkit --skill "remotion"
Install specific skill from multi-skill repository
# Description
Create programmatic videos using React with Remotion. Use when building video compositions, animations, or rendering videos programmatically. Triggers include creating video content with React, animating elements frame-by-frame, rendering videos to MP4/WebM/GIF, using spring/interpolate animations, building video editing apps, or deploying video rendering to AWS Lambda.
# SKILL.md
name: remotion
description: Create programmatic videos using React with Remotion. Use when building video compositions, animations, or rendering videos programmatically. Triggers include creating video content with React, animating elements frame-by-frame, rendering videos to MP4/WebM/GIF, using spring/interpolate animations, building video editing apps, or deploying video rendering to AWS Lambda.
Remotion
Remotion is a framework for creating videos programmatically using React. Videos are functions of frames over time.
Core Concepts
Video Properties:
- width, height: Dimensions in pixels
- fps: Frames per second
- durationInFrames: Total frames (duration = durationInFrames / fps)
First frame is 0, last frame is durationInFrames - 1.
Project Setup
npx create-video@latest # Create new project
npx remotion studio # Launch preview studio
npx remotion render src/index.ts CompositionId out.mp4 # Render video
Essential Hooks
import { useCurrentFrame, useVideoConfig } from 'remotion';
const MyComponent = () => {
const frame = useCurrentFrame(); // Current frame number (0-indexed)
const { fps, durationInFrames, width, height } = useVideoConfig();
return <div>Frame {frame} of {durationInFrames}</div>;
};
Composition Registration
Register compositions in src/Root.tsx:
import { Composition } from 'remotion';
export const RemotionRoot = () => (
<>
<Composition
id="MyVideo"
component={MyComponent}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
defaultProps={{ title: 'Hello' }}
/>
<Composition id="AnotherVideo" ... />
</>
);
Animation with interpolate()
Map frame values to animation properties:
import { interpolate, useCurrentFrame } from 'remotion';
const frame = useCurrentFrame();
// Fade in from frame 0-20
const opacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: 'clamp', // Prevent values > 1
});
// Fade in and out
const { durationInFrames } = useVideoConfig();
const fadeOpacity = interpolate(
frame,
[0, 20, durationInFrames - 20, durationInFrames],
[0, 1, 1, 0]
);
Options: extrapolateLeft, extrapolateRight: 'extend' | 'clamp' | 'identity' | 'wrap'
Spring Animations
Physics-based animations:
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({
frame,
fps,
config: { damping: 10, stiffness: 100, mass: 1 },
durationInFrames: 30, // Optional: constrain duration
});
// Combine spring with interpolate for custom ranges
const translateX = interpolate(spring({ frame, fps }), [0, 1], [0, 200]);
Easing Functions
import { interpolate, Easing } from 'remotion';
const value = interpolate(frame, [0, 30], [0, 100], {
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
// Or: Easing.ease, Easing.inOut(Easing.quad), Easing.bounce, etc.
});
Sequencing Content
Sequence - Time-shift children (useCurrentFrame becomes relative):
import { Sequence } from 'remotion';
<Sequence from={30} durationInFrames={60}>
<MyComponent /> {/* useCurrentFrame() starts at 0 when parent is at frame 30 */}
</Sequence>
Series - Play items one after another:
import { Series } from 'remotion';
<Series>
<Series.Sequence durationInFrames={30}><Intro /></Series.Sequence>
<Series.Sequence durationInFrames={60}><Main /></Series.Sequence>
<Series.Sequence durationInFrames={30}><Outro /></Series.Sequence>
</Series>
Loop - Repeat content:
import { Loop } from 'remotion';
<Loop durationInFrames={30} times={3}> {/* or times={Infinity} */}
<Animation />
</Loop>
Freeze - Pause at specific frame:
import { Freeze } from 'remotion';
<Freeze frame={10}>
<MyComponent /> {/* Always renders as if at frame 10 */}
</Freeze>
Layout & Media Components
import { AbsoluteFill, Img, Video, Audio, OffthreadVideo, staticFile } from 'remotion';
// Full-screen container
<AbsoluteFill style={{ backgroundColor: 'white' }}>
{/* Images - waits for load */}
<Img src={staticFile('image.png')} />
{/* Video - synchronized with timeline */}
<Video src={staticFile('clip.mp4')} volume={0.5} />
{/* OffthreadVideo - better performance for heavy videos */}
<OffthreadVideo src={staticFile('large.mp4')} />
{/* Audio */}
<Audio src={staticFile('music.mp3')} volume={0.8} />
</AbsoluteFill>
Video/Audio props: volume, playbackRate, muted, loop, startFrom, endAt
playbackRate limitations:
- Must be a constant value (e.g., playbackRate={2})
- Dynamic interpolation like playbackRate={interpolate(frame, [0, 100], [1, 5])} won't work correctly
- For variable speeds, extreme speeds (>4x), or guaranteed audio sync, pre-process with FFmpeg instead (see FFmpeg skill)
Static Files
Place files in public/ folder:
import { staticFile } from 'remotion';
const videoSrc = staticFile('videos/intro.mp4'); // -> /public/videos/intro.mp4
Input Props
Pass dynamic data to compositions:
// In composition
const { title, color } = getInputProps();
// CLI: npx remotion render ... --props='{"title":"Hello","color":"red"}'
// Or from file: --props=./data.json
Async Data Loading
import { delayRender, continueRender } from 'remotion';
const MyComponent = () => {
const [data, setData] = useState(null);
const [handle] = useState(() => delayRender()); // Block render
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(d => {
setData(d);
continueRender(handle); // Unblock render
});
}, [handle]);
if (!data) return null;
return <div>{data.title}</div>;
};
Color Interpolation
import { interpolateColors, useCurrentFrame } from 'remotion';
const frame = useCurrentFrame();
const color = interpolateColors(frame, [0, 30], ['#ff0000', '#0000ff']);
CLI Rendering
# Render to MP4
npx remotion render src/index.ts MyComposition out.mp4
# Common flags
--codec=h264|h265|vp8|vp9|gif|prores
--quality=80 # JPEG quality for frames
--scale=2 # 2x resolution
--frames=0-59 # Render specific frames
--props='{"key":"value"}'
--concurrency=4 # Parallel renders
Programmatic Rendering
import { bundle } from '@remotion/bundler';
import { renderMedia, selectComposition } from '@remotion/renderer';
const bundleLocation = await bundle({ entryPoint: './src/index.ts' });
const composition = await selectComposition({
serveUrl: bundleLocation,
id: 'MyComposition',
inputProps: { title: 'Hello' },
});
await renderMedia({
composition,
serveUrl: bundleLocation,
codec: 'h264',
outputLocation: 'out.mp4',
inputProps: { title: 'Hello' },
});
Lambda Rendering
Deploy and render in AWS Lambda for parallel, serverless rendering:
# Setup
npx remotion lambda policies user
npx remotion lambda functions deploy
# Deploy site
npx remotion lambda sites create src/index.ts --site-name=mysite
# Render
npx remotion lambda render <serve-url> MyComposition out.mp4
import { renderMediaOnLambda } from '@remotion/lambda';
const { bucketName, renderId } = await renderMediaOnLambda({
region: 'us-east-1',
functionName: 'remotion-render',
serveUrl: 'https://...',
composition: 'MyComposition',
codec: 'h264',
inputProps: { title: 'Hello' },
});
Player Component (Embed in React Apps)
import { Player } from '@remotion/player';
<Player
component={MyComposition}
durationInFrames={150}
fps={30}
compositionWidth={1920}
compositionHeight={1080}
style={{ width: '100%' }}
controls
loop
autoPlay
inputProps={{ title: 'Hello' }}
/>
Scene Transitions
The toolkit includes a transitions library at lib/transitions/ for scene-to-scene effects.
Using TransitionSeries
import { TransitionSeries, linearTiming } from '@remotion/transitions';
// Import custom transitions from lib (adjust path based on your project location)
import { glitch, lightLeak, clockWipe, checkerboard } from '../../../../lib/transitions';
// Or import from @remotion/transitions for official ones
import { slide, fade } from '@remotion/transitions/slide';
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={90}>
<TitleSlide />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={glitch({ intensity: 0.8 })}
timing={linearTiming({ durationInFrames: 30 })}
/>
<TransitionSeries.Sequence durationInFrames={120}>
<ContentSlide />
</TransitionSeries.Sequence>
</TransitionSeries>
Available Transitions
Custom (lib/transitions/):
| Transition | Options | Best For |
|---|---|---|
glitch() |
intensity, slices, rgbShift |
Tech demos, edgy reveals, cyberpunk |
rgbSplit() |
direction, displacement |
Modern tech, energetic transitions |
zoomBlur() |
direction, blurAmount |
CTAs, high-energy moments, impact |
lightLeak() |
temperature, direction |
Celebrations, film aesthetic, warm moments |
clockWipe() |
startAngle, direction, segments |
Time-related content, playful reveals |
pixelate() |
maxBlockSize, gridSize, scanlines, glitchArtifacts, randomness |
Retro/gaming, digital transformations |
checkerboard() |
gridSize, pattern, stagger, squareAnimation |
Playful reveals, structured transitions |
Checkerboard patterns: sequential, random, diagonal, alternating, spiral, rows, columns, center-out, corners-in
Official Remotion (@remotion/transitions/):
| Transition | Description |
|---|---|
slide() |
Push scene from direction |
fade() |
Simple crossfade |
wipe() |
Edge reveal |
flip() |
3D card flip |
Transition Examples
// Tech/cyberpunk feel
glitch({ intensity: 0.8, slices: 8, rgbShift: true })
// Warm celebration
lightLeak({ temperature: 'warm', direction: 'right' })
// High energy zoom
zoomBlur({ direction: 'in', blurAmount: 20 })
// Chromatic aberration
rgbSplit({ direction: 'diagonal', displacement: 30 })
// Clock sweep reveal
clockWipe({ direction: 'clockwise', startAngle: 0 })
// Retro pixelation
pixelate({ maxBlockSize: 50, glitchArtifacts: true })
// Checkerboard patterns
checkerboard({ pattern: 'diagonal', gridSize: 8 })
checkerboard({ pattern: 'spiral', gridSize: 10 })
checkerboard({ pattern: 'center-out', squareAnimation: 'scale' })
Timing Functions
import { linearTiming, springTiming } from '@remotion/transitions';
// Linear: constant speed
linearTiming({ durationInFrames: 30 })
// Spring: physics-based with bounce
springTiming({ config: { damping: 200 }, durationInFrames: 45 })
Duration Guidelines
| Type | Frames | Notes |
|---|---|---|
| Quick cut | 15-20 | Fast, punchy |
| Standard | 30-45 | Most common |
| Dramatic | 50-60 | Slow reveals |
| Glitch effects | 20-30 | Should feel sudden |
| Light leak | 45-60 | Needs time to sweep |
Preview Transitions
Run the showcase gallery to see all transitions:
cd showcase/transitions && npm run studio
Best Practices
- Frame-based animations only - Avoid CSS transitions/animations; they cause flickering
- Use fps from useVideoConfig() - Make animations frame-rate independent
- Clamp interpolations - Use
extrapolateRight: 'clamp'to prevent runaway values - Use OffthreadVideo - Better performance than
<Video>for complex compositions - delayRender for async - Always block rendering until data is ready
- staticFile for assets - Reference files from public/ folder correctly
Advanced API
For detailed API documentation on all hooks, components, renderer, Lambda, and Player APIs, see reference.md.
License Note
Remotion has a special license. Companies may need to obtain a license for commercial use. Check https://remotion.dev/license
Feedback & Contributions
If this skill is missing information or could be improved:
- Missing a pattern? Describe what you needed
- Found an error? Let me know what's wrong
- Want to contribute? I can help you:
- Update this skill with improvements
- Create a PR to github.com/digitalsamba/claude-code-video-toolkit
Just say "improve this skill" and I'll guide you through updating .claude/skills/remotion/SKILL.md.
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.