1实现原理 · 为什么它能做到
立论基础是 Remotion 的帧确定性:动画是当前帧的纯函数,因此可精确渲染任意帧、可 diff、可进 CI——这也是它敢「不设 seek harness」直接渲染精确帧的原因。
Build real MP4/GIF/WebM videos in React. Every frame is a pure function of `useCurrentFrame()`, so output is deterministic, scrubbable, diffable, and renderable in CI. The code-first alternative to After Effects for templated and data-driven motion graphics.
核心 API 面被压缩成 4 个原语:interpolate(时间→值且必须 clamp)、spring(物理缓动)、Sequence/Series(时间轴排布)、Composition+zod schema(参数化与可编辑 props)。
Always clamp `interpolate` unless an intentional overshoot is desired — by default it extrapolates linearly past the range, which produces opacity > 1 or negative values.
数据驱动是其差异化卖点:durationInFrames 可由 props 计算(calculateMetadata),数据一次定义、多输出渲染,适合「一行 CSV/一条记录一条视频」。
To make duration data-dependent, use `calculateMetadata` on the Composition to compute `durationInFrames` from props (e.g. number of rows × frames per row) before render.
音频与节拍同步被要求「离线检测、把时间戳烘进 props」,因为无头渲染没有实时音频时钟。
Detect beats offline (e.g. with `web-audio-beat-detector` or aubio) and bake the timestamps into props — never analyze audio at render time, since headless rendering has no realtime audio clock.
确定性纪律被写成禁止清单:不能用 Math.random / Date.now / 定时器,随机必须用 Remotion 的 random(seed)。
- Never use `Math.random()`, `Date.now()`, or animation timers — they break determinism. Use `random(seed)` from Remotion for stable per-frame randomness.
验证回路刻意分两段以省钱:先渲染起始/中段/末帧的 PNG 逐张检查,确认无误才编码整片;且要用「实际要发布的 props」而不是 defaultProps。
**Verify loop — render stills → inspect → encode.** Render single frames first (cheap, no video encode), inspect them, and encode the full video only once the frames are right.
「渲染器会撒谎,文件不会」:验证最终交付物时直接读编码后的 MP4 元数据并断言分辨率/fps(仓库脚本 probe-mp4.sh 用 ffprobe 实现)。
# Renders lie; the file doesn't. This reads resolution / codec / fps / duration straight from the
数据驱动/批量作业有专门的中间验收:先用一套代表性 props 跑 still 检查,再批量渲染,避免把同一个布局 bug 复制 N 份。
**Data-driven / batch**: verify ONE representative props set via stills *before* batch-rendering all rows — catch a layout bug once instead of N times.
reference 文件补齐了工程化面:CLI 旗标、programmatic 渲染循环、GLSL/Three.js 嵌入、确定性 checklist。
import {bundle} from '@remotion/bundler';
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | npx remotion(studio / still / render / compositions),远程拉取 Remotion 工具链 |
| package | remotion(运行时)/ @remotion/renderer / @remotion/bundler |
| package | zod + @remotion/zod-types(props 类型安全与 Studio 可编辑) |
| package | @remotion/three + three(在视频里驱动 Three.js 场景) |
| package | @remotion/google-fonts(无头渲染下预载字体,避免字体跳变) |
| package | web-audio-beat-detector / aubio(离线节拍检测,产出烘进 props 的时间戳) |
| cli | ffprobe(probe-mp4.sh 读取成片真实规格)/ ffmpeg(contact-sheet.sh 拼接 still) |
| network | iart.ai 引流链接(文档内,非运行时调用) |
4风险提醒 风险提醒:橙色 · 评估后使用
- 依赖远程包与本地执行渲染链(供应链 + 执行面) — 使用即 `npx remotion …`(从 npm 获取并执行 CLI),并在无头浏览器里 bundle 执行项目代码;版本受项目 package.json 影响。锁定版本、离线安装或用本地 node_modules 可收敛该面。
- 渲染开销可能远超预期 — Remotion 渲染是 Chromium 逐帧渲染,长视频/高分辨率/Three.js 场景成本高;skill 虽给了 --concurrency/--scale 与 still 先行策略,但未给任何预算或时长估算,容易在批量(N 行数据 → N 条视频)时失控。
- scripts/ 路径依赖仓库根工作目录 — SKILL.md 称 'Packaged helper (`scripts/`)',脚本实际在仓库根 motion-design/scripts/;按单 skill 粒度安装后照抄 `scripts/probe-mp4.sh` 可能找不到文件(同仓库 after-effects 的 .jsx 却在 skill 内)。
- 渲染期网络依赖可能破坏可重复性 — reference 建议用 @remotion/google-fonts 预载字体,即在渲染时访问 Google Fonts;无网络环境会失败或字体回退,导致成片与预期不一致(字体/文本溢出正是 checklist 要查的项)。
- 验收仍是「看图判断」为主 — 除成片 spec 断言(分辨率/fps/codec)可机械校验外,「文本是否溢出、安全区是否被压、数据绑定是否正确」由人/模型看图判断,没有自动断言;批量场景下依赖代表性样本抽样。
- 文档含商业引流 — reference 末尾含 iart.ai 的 UTM 链接,属该 14-pack 开源集合的统一转化位;不影响功能。
5第二遍独立确认
- [ok] 「无 seek harness、可直接渲染精确帧」的前提是否成立 — SKILL.md 与 reference 一以贯之地把确定性建立在「每帧是 useCurrentFrame 的纯函数」上,并用禁止清单(Math.random/Date.now/timers)+ random(seed) + delayRender/continueRender 兜住例外;因此 still --frame=N 能精确复现该帧。逻辑自洽,非空话。
- [ok] verify loop 的命令是否可执行(含末帧取值) — 命令为 `npx remotion still Promo out/f-start.png --frame=0` / --frame=75 / --frame=149,并注明「last frame = durationInFrames - 1」,另给 `npx remotion compositions` 用于反查 durationInFrames/fps。无未定义变量。
- [ok] probe-mp4.sh 的断言语义(首遍称「读真实 spec 并断言」) — 实读脚本:分辨率不等即 fail=1;fps 用 awk 容差 0.5 判定;codec 非 h264 只告警不 fail;末尾按 fail 决定 exit 0/1。首遍描述准确(未夸大「强制 h264」)。
- [discrepancy] scripts/ 路径语义(是否 skill 内自带) — SKILL.md 写 'Packaged helper (`scripts/`)',实际脚本在**仓库根** motion-design/scripts/,skills/remotion-video/ 目录内没有 scripts/(同仓库 after-effects 却自带 skills/after-effects/scripts/*.jsx)。按单 skill 粒度安装时,`scripts/contact-sheet.sh`、`scripts/probe-mp4.sh` 的相对路径可能解析不到;在仓库根工作则成立。属文档/打包口径问题,非功能缺陷。
- [ok] 外部依赖是否完整(含 reference 里的隐性依赖) — SKILL.md 显式提及 remotion、zod、@remotion/renderer、web-audio-beat-detector、aubio、staticFile;reference 补充 @remotion/bundler、@remotion/zod-types、@remotion/three、three、@remotion/google-fonts 与 --gl=angle/--scale/--concurrency 等旗标。已全部逐条登记;无未登记的第三方服务。
- [ok] 安全面:有无凭证/环境变量/隐蔽外发 — 全目录对 API_KEY/token/secret/env/curl/requests 零命中;脚本只做 ffprobe/ffmpeg 本地操作;网络面仅来自 npx 拉包与(reference 建议的)Google Fonts 预载。第一遍 orange 判定的依据(远程包依赖)成立,且未发现应升档的凭证/绕过行为。
- [ok] 数据驱动「先验一套代表 props」是否真的写进流程 — 'Data-driven / batch: verify ONE representative props set via stills before batch-rendering all rows' 位于 verify loop 小节内,且 Output contract 要求「渲染时用实际要发布的 props,而不是 defaultProps」('render with the SAME props you'll ship')。流程上有落点。
- [ok] 与 logo-animation 的 tier 路由一致性 — 本 skill 自述 'this is the heavy-tier counterpart to a web scene's ?t=N';logo-animation 侧写 'For web/SVG/Lottie delivery use this standalone-HTML loop; for a video logo sting, render via the remotion-video verify loop instead.'。两端互指一致。
6结论
3d9caacebfc580bf…3c129f769d