什么是 Remotion
Remotion 是 2021 年起瑞典团队开发的 React 视频框架:用 React 组件描述视频帧,最后用 FFmpeg 渲染成 MP4。优势:
- 代码即视频:可以组件化、参数化、用 Git 版本管理
- 数据驱动:JSON 配置 → 自动生成几十条视频
- AI 友好:搭配 LLM 生成文案 + 自动化脚本,几分钟产出可发布短视频
前置环境
- Node.js 18+(推荐 22)
- FFmpeg(Remotion 渲染依赖)
- React 基础
- 一台能跑 Chrome 的电脑(Remotion Studio 用 Chrome preview)
创建项目
1
2
3
4
5
6
7
8
9
10
| npx create-video@latest
# create-video@4.0.443
# Welcome to Remotion!
# 选择模板
# > Hello World 新手先用这个
# Next.js SaaS template
# Blank Nothing except an empty canvas
# Recorder A video production tool built entirely in JavaScript
# ...
|
按提示选:
- Add TailwindCSS: yes
- Add agent skills: yes(如果用 Claude Code 协作)
- 一路回车
用 IDEA 打开
1
2
3
4
5
6
7
8
9
10
| # 装依赖
npm install
# 装 Studio CLI
npm i @remotion/cli
# 启动 Studio(默认 3000 端口)
npm dev
# 或
npx remotion studio
|
浏览器打开 http://localhost:3000,左侧是组件树,中间是时间线,右侧是实时预览。
渲染导出
1
2
| # 渲染当前 Composition 为 MP4
npx remotion render out/HelloWorld.mp4
|
默认输出在 out/HelloWorld.mp4。
核心 API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import { useCurrentFrame, useVideoConfig, AbsoluteFill, Img, Audio, Sequence } from 'remotion';
export const HelloWorld = () => {
const frame = useCurrentFrame();
const { fps, durationInFrames, width, height } = useVideoConfig();
return (
<AbsoluteFill style={{ backgroundColor: 'white' }}>
<h1 style={{
fontSize: 80,
textAlign: 'center',
paddingTop: 200,
color: frame > 30 ? 'red' : 'black',
}}>
第 {Math.round(frame / fps)} 秒
</h1>
</AbsoluteFill>
);
};
|
useCurrentFrame() 返回当前帧号(从 0 开始),useVideoConfig() 返回 fps / 时长 / 宽高。AbsoluteFill 是定位容器。
关键概念
- Composition:一段视频的元数据(fps、width、height、durationInFrames、组件)
- Sequence:在指定时间区间内显示子组件
- useCurrentFrame / useVideoConfig:读取当前播放状态
- staticFile():引用 public/ 下的静态资源
常用内置组件
| 组件 | 用途 |
|---|
<AbsoluteFill> | 绝对定位全屏容器 |
<Sequence from={30} durationInFrames={60}> | 1~3 秒显示子组件 |
<Img src={staticFile('cover.png')} /> | 显示图片 |
<Audio src={staticFile('bgm.mp3')} /> | 播放音频 |
<Video src={staticFile('demo.mp4')} /> | 播放视频 |
<Series> | 多个 Sequence 串联 |
动画模式
弹簧物理(spring)
1
2
3
4
5
6
7
8
9
10
| import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({
frame,
fps,
config: { damping: 10, stiffness: 100, mass: 0.5 },
});
|
缓动(interpolate)
1
2
3
4
| import { interpolate } from 'remotion';
const opacity = interpolate(frame, [0, 30, 60, 90], [0, 1, 1, 0]);
const translateY = interpolate(frame, [0, 30], [100, 0]);
|
数据驱动批量生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // 配合 LLM 生成 JSON 数组
const videos = [
{ id: 'v1', title: '春节特辑', duration: 60 },
{ id: 'v2', title: '清明特辑', duration: 60 },
];
export const RemotionRoot = () => {
return videos.map(v => (
<Composition
key={v.id}
id={v.id}
component={MyVideo}
durationInFrames={v.duration * 30}
fps={30}
width={1080}
height={1920}
/>
));
};
|
配合 Claude Code 写一个生成脚本:
1
2
3
4
5
| # 调用 mmx-cli 生成文案 + TTS 配音
# 然后批量渲染
for id in v1 v2 v3; do
npx remotion render "$id" "out/$id.mp4"
done
|
TailwindCSS 集成
1
2
3
4
5
6
7
| # 创建项目时已经选了 TailwindCSS
# 组件里直接用
export const Card = () => (
<AbsoluteFill className="bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
<h1 className="text-6xl font-bold text-white">Hello</h1>
</AbsoluteFill>
);
|
性能优化
- 减少状态:Remotion 渲染是逐帧的,组件内 React state 频繁变化会拖慢
- 避免 useEffect:用
useCurrentFrame 替代 - 静态资源:用
staticFile() 引用,Remotion 会在打包时复制 - Chrome 远程调试:Studio 启动时加
--no-sandbox 在 Docker 里
常见问题
渲染卡死 / 内存溢出
1
2
3
4
5
| # 加 --concurrency 限制并发
npx remotion render --concurrency=2
# 加 --jpeg-quality 降低质量换速度
npx remotion render --jpeg-quality=80
|
Windows FFmpeg 路径
1
2
3
| # 把 C:\ffmpeg\bin 加到 PATH
# 或用 Scoop
scoop install ffmpeg
|
Linux 服务器无 GUI 渲染
1
2
3
4
5
| # 装 headless Chrome
sudo apt install -y chromium-browser
# Remotion 自动用 headless Chrome
npx remotion render
|
进阶:Remotion + Vite 独立集成
不用 create-video 脚手架,把 Remotion 集成进现有 Vite 项目:
1
| npm i @remotion/cli @remotion/renderer
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // src/Root.tsx
import { Composition } from 'remotion';
import { MyVideo } from './MyVideo';
export const RemotionRoot = () => (
<>
<Composition
id="MyVideo"
component={MyVideo}
durationInFrames={300}
fps={30}
width={1920}
height={1080}
/>
</>
);
|
1
2
3
4
5
| // remotion.config.ts
import { Config } from '@remotion/cli/config';
Config.setVideoImageFormat('jpeg');
Config.setConcurrency(4);
|
下一步
参考资料
- Remotion 官方:https://www.remotion.dev/docs
- Remotion 中文文档:https://remotion-zh-cn-doc.vercel.app/
- Remotion Gallery:https://www.remotion.dev/showcase