Featured image of post Remotion 视频创作:React 写视频的工程化实践

Remotion 视频创作:React 写视频的工程化实践

Remotion 视频创作框架实战:从零搭建 React 视频项目、Studio 预览、render 导出 MP4、TailwindCSS 集成、与 AI 字幕/动效插件协作。

什么是 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
使用 Hugo 构建
主题 StackJimmy 设计