Remotion 运动图形
Remotion 将 React 组件逐帧渲染为视频。代码质量并非瓶颈——运动设计的工艺才是。未经训练的输出会产生线性缓动、仅透明度变化的淡入、同时入场、纯色平面、毫无纹理。这就是“通用的 AI 视频”外观。此技能旨在避免这种情况。
不可协商的规则(适用于每个合成)
- 绝不使用线性插值。 每个
interpolate()都必须有一个缓动曲线;每个入场都优先使用spring()。始终设置extrapolateLeft/Right: "clamp"。 - 入场同时动画 2–3 个属性(不透明度 + translateY + 缩放)。禁止单独使用淡入。
- 所有元素错开入场。 列表、文字、光束、卡片:偏移 3–6 帧。没有元素会同时进入。
- 出场存在并且比入场更快(约 10 帧对约 20 帧)。
- 每个场景有五层堆栈,从下到上:背景网格 → 素材 → 图形/文字 → 调色 → 颗粒 + 暗角。绝不能使用纯色平铺背景。
- 每张静态图片都应用 Ken Burns 效果(缓慢缩放 1→1.08 + 平移)。每个视频素材都使用
<OffthreadVideo>,而不是<Video>。 - 静态元素保持呼吸感:屏幕上持续超过 2 秒的元素应有正弦波微运动。
- 所有时间基于
fps通过useVideoConfig()获取。没有魔数帧。 - 项目顶部定义一个主题对象(颜色、缓动、弹簧预设、字体)。绝不在组件中内联十六进制颜色或缓动。
- 渲染、提取帧、检查、修复、重新渲染。 切勿交付未经验证的渲染。此循环是强制性的——请参看下面的验证部分。
工作流
第 1 步 — 确定范围
确定:时长、fps(默认 30;仅当有大量快速运动时用 60)、尺寸(1080×1920 的 Reels/Shorts,1920×1080 的横屏)、有哪些素材(图片、视频、音频、标志),以及这是一个新合成还是对现有项目的编辑。如果是编辑现有项目:先完整阅读 src/ 目录,找到主题(或创建一个),并在添加新功能之前重构违反上述规则的部分。
第 2 步 — 设置
新项目:
npm install remotion @remotion/cli react react-dom
# 可选:@remotion/transitions @remotion/motion-blur @remotion/google-fonts
从此技能复制 assets/theme.ts 到 src/theme.ts,并根据用户的品牌调整调色板。目录结构:src/index.ts (registerRoot) → src/Root.tsx (Composition, duration/fps/size) → src/scenes/*.tsx → src/components/*.tsx。用户素材放在 public/ 中,通过 staticFile() 加载。
第 3 步 — 构建
阅读 references/motion-patterns.md 获取可复用组件的实现 (BgMesh, Grade, Grain, Vignette, KenBurns, WordReveal, Stagger, Counter, Spark, transitions, parallax)。基于这些模式组合场景。关于节奏、韵律、排版、色彩搭配和声音设计规则,请阅读 references/design-rules.md。
场景节奏:高潮 → 停顿 (15–20 帧静止) → 构建 → 高潮。前 15 帧内必须有东西在动。连续超过 90 帧没有新的视觉元素。
第 4 步 — 渲染
npx remotion render src/index.ts <CompId> out/video.mp4 --codec h264 --crf 17
Remotion 需要一个 Chromium 二进制文件。如果自动下载失败(沙箱环境、离线 CI),找到它并显式指定路径:
which chromium chromium-browser google-chrome 2>/dev/null
ls /opt/pw-browsers 2>/dev/null # Playwright 安装在此处
npx remotion render ... --browser-executable=<路径>
如果完整版 Chrome 报错 "Old Headless mode has been removed",改用 headless_shell 二进制文件(Playwright 附带了一个,路径类似 chromium_headless_shell-*/chrome-linux/headless_shell)。
第 5 步 — 验证(强制性,不可跳过)
在关键时间点提取帧并进行视觉检查。便携方法——适用于没有系统 ffmpeg 的机器,渲染精确帧:
for f in 15 45 90 150; do
npx remotion still src/index.ts <CompId> out/check_$f.png --frame $f --overwrite
done
如果系统 ffmpeg 可用,从完成的 mp4 中提取也能验证编码本身(-ss 定位比 select= 过滤器更便携,后者的引号在某些 shell 和 Remotion 自带的 ffmpeg 中会出错):
ffmpeg -v error -ss 1.5 -i out/video.mp4 -frames:v 1 check_1.png
检查并按频率顺序修复:
- 间距 bug:
gap/margin使用em时相对于父元素字体大小(通常是 16px),而不是文字本身的大小——在大号文字周围的 flex 容器中使用 px 值。 - 文字溢出或触及框架边缘(对于 9:16 格式,将关键内容保持在垂直中间 75% 区域内——平台 UI 会遮挡顶部/底部)。
- 元素在其入场前或出场后可见(缺少 clamp)。
- 颜色/对比度问题:每帧中英雄色出现在超过一个元素上,深色文字在调色图层上难以阅读。
- 图层顺序错误(颗粒/暗角必须在最上层,调色在内容之上)。
修复 → 重新渲染 → 重新提取 → 重新检查。只有在通过干净检查后才可交付。然后运行
references/design-rules.md底部的最终检查清单。
编辑用户现有素材
要增强现有的 mp4 文件(添加字幕、调色、片头/片尾),而非从头构建:将文件放入 public/,使用 <OffthreadVideo src={staticFile("clip.mp4")} /> 作为素材层渲染,根据片段长度设置合成时长,并在其上方叠加图形/调色/颗粒。在设置合成之前,使用 ffprobe 获取片段的时长和 fps。对于与语音同步的文字字幕,请参阅 references/motion-patterns.md 中的字幕部分。
参考文件
references/motion-patterns.md— 可复制粘贴的组件库:背景、调色/颗粒/暗角、Ken Burns、文字揭示、计数器、转场、视差、音频同步、字幕。在编写组件之前阅读此文件。references/design-rules.md— 调色板、排版规则、场景架构、声音设计、交付前检查清单。在设计场景和最终交付前阅读此文件。assets/theme.ts— 要复制到每个项目中的主题模板。
需要主动避免的常见故障模式
- 将 emoji 用作图标。 Emoji 会渲染为全色平台字形(绿色 ✳️、蓝色 🌐),忽略你的调色板并悄然打破单英雄色规则,而且它们会坐在你给它们的背景上(橙色吉祥物在橙色瓷砖上 = 不可见)。使用主题颜色的 CSS/SVG 绘制字形,或者对照提取的帧逐一验证每个 emoji。
- 没有音效素材不是跳过音频的理由。 通过 Node 脚本合成一个最小音效包,输出为 16 位 WAV 文件(噪音爆发嗖声、音高下降砰声、正弦砰动底鼓/贝斯、失谐正弦垫音),放入
public/sfx/——请查看仓库中的examples/scripts/。零下载,完全确定性。 - 生成一个巨大的组件,而不是有主题、可重用的片段。
durationInFrames在 Composition 和场景内容之间不匹配(导致静音时段)。- 重新渲染时忘记使用
--overwrite,然后检查了旧文件。 - 字体:主角文字永远不要依赖系统默认字体;通过
@remotion/google-fonts或@font-face+staticFile加载显示字体。 - 试图向用户“描述”结果,而不是渲染出来并验证它。