remotion
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRemotion
Remotion
Remotion is a framework for creating videos programmatically using React. Videos are functions of frames over time.
Remotion是一个基于React的程序化视频创建框架。视频可以看作是随时间变化的帧函数。
Core Concepts
核心概念
Video Properties:
- ,
width: Dimensions in pixelsheight - : Frames per second
fps - : Total frames (duration = durationInFrames / fps)
durationInFrames
First frame is 0, last frame is durationInFrames - 1.
视频属性:
- ,
width: 像素维度height - : 每秒帧数
fps - : 总帧数(时长 = 总帧数 / fps)
durationInFrames
第一帧索引为0,最后一帧索引为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 videobash
npx create-video@latest # 创建新项目
npx remotion studio # 启动预览工作室
npx remotion render src/index.ts CompositionId out.mp4 # 渲染视频Essential Hooks
核心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>;
};tsx
import { useCurrentFrame, useVideoConfig } from 'remotion';
const MyComponent = () => {
const frame = useCurrentFrame(); // 当前帧编号(从0开始索引)
const { fps, durationInFrames, width, height } = useVideoConfig();
return <div>第 {frame} 帧,共 {durationInFrames} 帧</div>;
};Composition Registration
合成注册
Register compositions in :
src/Root.tsxtsx
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" ... />
</>
);在中注册合成内容:
src/Root.tsxtsx
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()
插值动画(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: , : | | |
extrapolateLeftextrapolateRight'extend''clamp''identity''wrap'将帧值映射到动画属性:
tsx
import { interpolate, useCurrentFrame } from 'remotion';
const frame = useCurrentFrame();
// 第0-20帧淡入
const opacity = interpolate(frame, [0, 20], [0, 1], {
extrapolateRight: 'clamp', // 防止值超过1
});
// 淡入后淡出
const { durationInFrames } = useVideoConfig();
const fadeOpacity = interpolate(
frame,
[0, 20, durationInFrames - 20, durationInFrames],
[0, 1, 1, 0]
);配置项: , : | | |
extrapolateLeftextrapolateRight'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]);基于物理效果的动画:
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, // 可选:限制动画时长
});
// 结合spring和interpolate实现自定义范围动画
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.
});tsx
import { interpolate, Easing } from 'remotion';
const value = interpolate(frame, [0, 30], [0, 100], {
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
// 也可以使用:Easing.ease, Easing.inOut(Easing.quad), Easing.bounce等
});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>Sequence - 偏移子元素的时间轴(useCurrentFrame变为相对时间):
tsx
import { Sequence } from 'remotion';
<Sequence from={30} durationInFrames={60}>
<MyComponent /> {/* 当父组件处于第30帧时,useCurrentFrame()从0开始计数 */}
</Sequence>Series - 按顺序播放多个内容项:
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 - 重复播放内容:
tsx
import { Loop } from 'remotion';
<Loop durationInFrames={30} times={3}> {/* 也可以设置times={Infinity}无限循环 */}
<Animation />
</Loop>Freeze - 固定在特定帧:
tsx
import { Freeze } from 'remotion';
<Freeze frame={10}>
<MyComponent /> {/* 始终渲染为第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: , , , , ,
volumeplaybackRatemutedloopstartFromendAtplaybackRate- Must be a constant value (e.g., )
playbackRate={2} - Dynamic interpolation like won't work correctly
playbackRate={interpolate(frame, [0, 100], [1, 5])} - For variable speeds, extreme speeds (>4x), or guaranteed audio sync, pre-process with FFmpeg instead (see FFmpeg skill)
tsx
import { AbsoluteFill, Img, Video, Audio, OffthreadVideo, staticFile } from 'remotion';
// 全屏容器
<AbsoluteFill style={{ backgroundColor: 'white' }}>
{/* 图片组件 - 等待加载完成后渲染 */}
<Img src={staticFile('image.png')} />
{/* 视频组件 - 与时间轴同步 */}
<Video src={staticFile('clip.mp4')} volume={0.5} />
{/* OffthreadVideo组件 - 处理大型视频时性能更优 */}
<OffthreadVideo src={staticFile('large.mp4')} />
{/* 音频组件 */}
<Audio src={staticFile('music.mp3')} volume={0.8} />
</AbsoluteFill>视频/音频组件属性: , , , , ,
volumeplaybackRatemutedloopstartFromendAtplaybackRate- 必须是常量值(例如:)
playbackRate={2} - 动态插值如无法正常工作
playbackRate={interpolate(frame, [0, 100], [1, 5])} - 如果需要变速、超高速(>4倍速)或确保音频同步,建议先使用FFmpeg预处理(详见FFmpeg相关技能)
Static Files
静态文件
Place files in folder:
public/tsx
import { staticFile } from 'remotion';
const videoSrc = staticFile('videos/intro.mp4'); // -> /public/videos/intro.mp4将文件放置在文件夹中:
public/tsx
import { staticFile } from 'remotion';
const videoSrc = staticFile('videos/intro.mp4'); // 对应路径:/public/videos/intro.mp4Input 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向合成内容传递动态数据:
tsx
// 在合成组件中
const { title, color } = getInputProps();
// CLI命令:npx remotion render ... --props='{"title":"Hello","color":"red"}'
// 也可以从文件读取:--props=./data.jsonAsync 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>;
};tsx
import { delayRender, continueRender } from 'remotion';
const MyComponent = () => {
const [data, setData] = useState(null);
const [handle] = useState(() => delayRender()); // 阻止渲染,等待数据加载
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(d => {
setData(d);
continueRender(handle); // 数据加载完成,继续渲染
});
}, [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']);tsx
import { interpolateColors, useCurrentFrame } from 'remotion';
const frame = useCurrentFrame();
const color = interpolateColors(frame, [0, 30], ['#ff0000', '#0000ff']);CLI Rendering
CLI渲染
bash
undefinedbash
undefinedRender to MP4
渲染为MP4格式
npx remotion render src/index.ts MyComposition out.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
undefined--codec=h264|h265|vp8|vp9|gif|prores
--quality=80 # 帧的JPEG质量
--scale=2 # 2倍分辨率
--frames=0-59 # 渲染指定帧范围
--props='{"key":"value"}'
--concurrency=4 # 并行渲染数量
undefinedProgrammatic 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' },
});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
Lambda渲染
Deploy and render in AWS Lambda for parallel, serverless rendering:
bash
undefined部署到AWS Lambda实现并行、无服务器渲染:
bash
undefinedSetup
初始化配置
npx remotion lambda policies user
npx remotion lambda functions deploy
npx remotion lambda policies user
npx remotion lambda functions deploy
Deploy site
部署项目站点
npx remotion lambda sites create src/index.ts --site-name=mysite
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' },
});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)
播放器组件(嵌入React应用)
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' }}
/>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 for scene-to-scene effects.
lib/transitions/工具包包含一个过渡效果库,位于,用于实现场景间的切换效果。
lib/transitions/Using TransitionSeries
使用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>tsx
import { TransitionSeries, linearTiming } from '@remotion/transitions';
// 从lib导入自定义过渡效果(根据项目位置调整路径)
import { glitch, lightLeak, clockWipe, checkerboard } from '../../../../lib/transitions';
// 也可以从@remotion/transitions导入官方过渡效果
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 |
|---|---|---|
| | Tech demos, edgy reveals, cyberpunk |
| | Modern tech, energetic transitions |
| | CTAs, high-energy moments, impact |
| | Celebrations, film aesthetic, warm moments |
| | Time-related content, playful reveals |
| | Retro/gaming, digital transformations |
| | Playful reveals, structured transitions |
Checkerboard patterns: , , , , , , , ,
sequentialrandomdiagonalalternatingspiralrowscolumnscenter-outcorners-inOfficial Remotion (@remotion/transitions/):
| Transition | Description |
|---|---|
| Push scene from direction |
| Simple crossfade |
| Edge reveal |
| 3D card flip |
自定义效果(lib/transitions/):
| 过渡效果 | 配置项 | 适用场景 |
|---|---|---|
| | 技术演示、前卫风格的揭示效果、赛博朋克风格 |
| | 现代科技风格、充满活力的过渡 |
| | 行动号召(CTA)、高能量时刻、冲击力效果 |
| | 庆祝场景、胶片美学、温馨时刻 |
| | 时间相关内容、趣味揭示效果 |
| | 复古/游戏风格、数字转型效果 |
| | 趣味揭示效果、结构化过渡 |
Checkerboard可用模式: , , , , , , , ,
sequentialrandomdiagonalalternatingspiralrowscolumnscenter-outcorners-in官方Remotion过渡效果(@remotion/transitions/):
| 过渡效果 | 描述 |
|---|---|
| 从指定方向推入新场景 |
| 简单的交叉淡入淡出 |
| 边缘擦除揭示 |
| 3D卡片翻转效果 |
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' })tsx
// 科技/赛博朋克风格
glitch({ intensity: 0.8, slices: 8, rgbShift: true })
// 温馨庆祝风格
lightLeak({ temperature: 'warm', direction: 'right' })
// 高能量缩放效果
zoomBlur({ direction: 'in', blurAmount: 20 })
// 色差效果
rgbSplit({ direction: 'diagonal', displacement: 30 })
// 时钟扫过揭示效果
clockWipe({ direction: 'clockwise', startAngle: 0 })
// 复古像素化效果
pixelate({ maxBlockSize: 50, glitchArtifacts: true })
// 棋盘格模式示例
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 })tsx
import { linearTiming, springTiming } from '@remotion/transitions';
// 线性时序:匀速变化
linearTiming({ durationInFrames: 30 })
// 弹簧时序:基于物理效果的弹性变化
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 |
| 类型 | 帧数 | 说明 |
|---|---|---|
| 快速切换 | 15-20 | 快速、有力的过渡 |
| 标准过渡 | 30-45 | 最常用的过渡时长 |
| 戏剧性揭示 | 50-60 | 缓慢的揭示效果 |
| 故障效果 | 20-30 | 应给人突然的感觉 |
| 漏光效果 | 45-60 | 需要足够时间完成扫过动画 |
Preview Transitions
预览过渡效果
Run the showcase gallery to see all transitions:
bash
cd showcase/transitions && npm run studio运行展示画廊查看所有过渡效果:
bash
cd showcase/transitions && npm run studioBest Practices
最佳实践
- Frame-based animations only - Avoid CSS transitions/animations; they cause flickering
- Use fps from useVideoConfig() - Make animations frame-rate independent
- Clamp interpolations - Use to prevent runaway values
extrapolateRight: 'clamp' - Use OffthreadVideo - Better performance than for complex compositions
<Video> - delayRender for async - Always block rendering until data is ready
- staticFile for assets - Reference files from public/ folder correctly
- 仅使用基于帧的动画 - 避免使用CSS过渡/动画,否则会导致闪烁
- 使用useVideoConfig()中的fps - 让动画独立于帧率
- 限制插值范围 - 使用防止值失控
extrapolateRight: 'clamp' - 使用OffthreadVideo - 处理复杂合成时性能优于
<Video> - 异步加载使用delayRender - 始终在数据加载完成前阻止渲染
- 使用staticFile引用资源 - 正确引用public/文件夹中的文件
Advanced API
高级API
For detailed API documentation on all hooks, components, renderer, Lambda, and Player APIs, see reference.md.
关于所有Hooks、组件、渲染器、Lambda和Player API的详细文档,请查看reference.md。
License Note
许可证说明
Remotion has a special license. Companies may need to obtain a license for commercial use. Check https://remotion.dev/license
Remotion采用特殊许可证。商业使用可能需要企业获取许可证。详情请查看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如果本技能缺少某些信息或可以改进:
- 缺少某种模式? 描述你的需求
- 发现错误? 告知问题所在
- 想要贡献? 我可以帮你:
- 改进本技能的内容
- 向github.com/digitalsamba/claude-code-video-toolkit提交PR
只需说“优化本技能”,我会引导你更新文件。
.claude/skills/remotion/SKILL.md