Skip to content
Back to skills

Remotion

ASecurity

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.

  • 2,159 stars
  • 0 votes
  • 0 copies
  • 9 views
  • Added February 8, 2026
developmentgobashreactspringawsgitapiperformancedocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned February 12, 2026

npx -y skills add digitalsamba/claude-code-video-toolkit --skill remotion --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Remotion?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Remotion
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/digitalsamba-remotion/badge)](https://www.skillsdirectory.com/skills/digitalsamba-remotion)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
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

```bash
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

```tsx
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`:

```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:

```tsx
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:

```tsx
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

```tsx
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):

```tsx
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:

```tsx
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:

```tsx
import { Loop } from 'remotion';

<Loop durationInFrames={30} times={3}>  {/* or times={Infinity} */}
  <Animation />
</Loop>
```

**Freeze** - Pause at specific frame:

```tsx
import { Freeze } from 'remotion';

<Freeze frame={10}>
  <MyComponent />  {/* Always renders as if at frame 10 */}
</Freeze>
```

## Layout & Media Components

```tsx
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:

```tsx
import { staticFile } from 'remotion';

const videoSrc = staticFile('videos/intro.mp4');  // -> /public/videos/intro.mp4
```

## Input Props

Pass dynamic data to compositions:

```tsx
// In composition
const { title, color } = getInputProps();

// CLI: npx remotion render ... --props='{"title":"Hello","color":"red"}'
// Or from file: --props=./data.json
```

## Async Data Loading

```tsx
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

```tsx
import { interpolateColors, useCurrentFrame } from 'remotion';

const frame = useCurrentFrame();
const color = interpolateColors(frame, [0, 30], ['#ff0000', '#0000ff']);
```

## CLI Rendering

```bash
# 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

```tsx
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:

```bash
# 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
```

```tsx
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)

```tsx
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

```tsx
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

```tsx
// 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

```tsx
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:

```bash
cd showcase/transitions && npm run studio
```

## Best Practices

1. **Frame-based animations only** - Avoid CSS transitions/animations; they cause flickering
2. **Use fps from useVideoConfig()** - Make animations frame-rate independent
3. **Clamp interpolations** - Use `extrapolateRight: 'clamp'` to prevent runaway values
4. **Use OffthreadVideo** - Better performance than `<Video>` for complex compositions
5. **delayRender for async** - Always block rendering until data is ready
6. **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](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:
  1. Update this skill with improvements
  2. 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`.

Files in this skill

  • SKILL.md12.3 KB
  • reference.md10.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.