Remotion template-blank 空模板实战指南:从空画布到跑通预览与视频渲染
template-blank 是 Remotion 官方脚手架中刻意保持“零内容”的起步模板,只包含一个能注册、可预览、可渲染的最小 React 组合,不附带任何示例动画、素材或依赖,适合已经熟悉 Remotion、希望用 AI 辅助生成代码,或想从真正干净的基础上开始一个新视频项目的开发者。本文以 packages/template-blank 内的 README.md 为主体,结合其源码与配置文件逐层拆解模板的入口链路、Composition 声明、四条核心命令以及 remotion.config.ts 配置,读完你既能独立跑通“安装—预览—渲染—升级”全流程,也能在这个空骨架上安全地开始填充自己的第一帧画面。
什么是 template-blank:一个刻意留白的起点
在 Remotion 的模板体系中,template-blank 的定位非常特殊。打开 create-video 的模板注册表,可以看到它的官方描述是:
Nothing except an empty canvas(除了一块空画布之外什么都没有)
同时注册表里还给出了它的推荐使用场景:如果你已经用过 Remotion,或者计划用 AI 来编写代码,那么它是最合适的起点——因为它没有 Hello World 模板中那些演示用的旋转 Logo 和插值动画,不会有任何需要先删除的“示例残留”。模板仓库本身的包名是 template-empty,目录映射为 template-blank,这一内一外的命名也暗示了它的特性:仓库包体是空的,连依赖也精简到不能再少。
对比同仓库的 template-helloworld/package.json,后者额外引入了 zod 与 @remotion/zod-types 用于属性校验演示;而 template-blank 的 package.json 运行时依赖只有三个:remotion、@remotion/cli、react 与 react-dom(React 版本为 19.2.3),没有任何多余第三方库。
模板文件结构解剖:四个源码文件讲清注册链路
template-blank 的全部业务源码只包含三个文件与若干工程配置,结构极其直观:
template-blank/
├── src/
│ ├── index.ts # 入口:调用 registerRoot 注册根组件
│ ├── Root.tsx # 根组件:组装所有 Composition
│ └── Composition.tsx # 声明一个名为 MyComp 的 Composition
├── package.json # 脚本与依赖
├── remotion.config.ts # Remotion 构建/渲染配置
├── tsconfig.json
└── eslint.config.mjs
入口文件 index.ts:registerRoot 在做什么
src/index.ts 全文只有三行:
import { registerRoot } from "remotion";
import { RemotionRoot } from "./Root";
registerRoot(RemotionRoot);
registerRoot 是 Remotion 的核心注册函数,其真实实现在 packages/core/src/register-root.ts 中。从源码可以看到它内部维护了一个模块级的 Root 变量,并做了两道校验:
- 传入的不是有效组件(
!comp)时抛出错误; - 重复调用
registerRoot()时抛出错误(同一进程只能注册一次)。
注册成功后,组件会通过监听者机制通知等待方。同文件还暴露了 getRoot() 与 waitForRoot(fn):前者直接取回已注册的根组件,后者在组件尚未注册时把回调挂入监听队列、注册完成后立即执行。Remotion Studio、渲染器在拉起项目时正是通过这一机制获取你的根组件——这就是“为什么每个 Remotion 项目都必须有一个入口去调用 registerRoot”的原因。
Root.tsx:根组件只做一件事
src/Root.tsx 返回一个 Fragment,内部渲染 MyComposition:
export const RemotionRoot: React.FC = () => {
return (
<>
<MyComposition />
</>
);
};
在一个真正的项目里,Root 会逐渐演变成“所有视频的目录页”——每新增一个视频/组合,就往这里加一行。template-blank 只保留一个,因为空模板不需要展示多个组合。
Composition.tsx:视频“规格”的声明处
src/Composition.tsx 是模板中最值得研读的文件,它声明了渲染的规格:
import { CalculateMetadataFunction, Composition } from "remotion";
type Props = {};
const calculateMetadata: CalculateMetadataFunction<Props> = () => {
return {};
};
export const MyComposition = () => {
return (
<Composition
id="MyComp"
component={MyComponent}
durationInFrames={60}
fps={30}
width={1280}
height={720}
calculateMetadata={calculateMetadata}
/>
);
};
export const MyComponent: React.FC<Props> = () => {
return null;
};
<Composition> 是 Remotion 注册一段可渲染视频的声明式组件,这里每个属性的含义与当前值如下:
| 属性 | 当前值 | 含义 |
|---|---|---|
id |
MyComp |
组合的唯一标识,命令行渲染、URL 定位时都使用它 |
component |
MyComponent |
真正渲染每一帧画面的 React 组件 |
durationInFrames |
60 |
总帧数,60 帧 ÷ 30fps = 2 秒视频 |
fps |
30 |
帧率 |
width / height |
1280 / 720 |
画布尺寸,即 720p |
calculateMetadata |
返回空对象 | 异步元数据钩子(占位) |
calculateMetadata 的类型是 CalculateMetadataFunction<Props>,官方用它支持在拿到数据后再动态决定时长、帧率或分辨率(例如先从远端读取素材长度)。模板里它是一个返回空对象的占位实现,相当于不注入任何动态元数据,方便你在需要时直接填入真实的异步计算逻辑。
值得注意:MyComponent 目前 return null,也就是说这是一块真正“什么都没有画”的 1280×720、30fps、时长 2 秒的空画布——所有后续视觉内容都从这里开始生长。
四条核心命令:从依赖安装到渲染完成
README 给出了一个最小可用的命令闭环,下面逐条拆解它们在模板中的真实行为。
1. 安装依赖
npm install
根据 package.json,运行时依赖为 remotion、@remotion/cli、react、react-dom,开发依赖包含 @remotion/eslint-config-flat、eslint、typescript、prettier 与 React 类型声明。需要说明的是:在当前 monorepo 源码树中依赖以 workspace:* 引用(package.json 中的 remotion: "workspace:*"),这是仓库内部联调方式;当你通过脚手架在独立目录创建项目时,得到的是常规的已发布版本号。若使用其他包管理器,README 的命令同样适配 yarn / pnpm 的等价形式。
2. 启动预览(Remotion Studio)
npm run dev
package.json 中该脚本的真实内容是 remotion studio,即启动 Remotion Studio——Remotion 官方的时间线可视化预览界面。它会读取入口文件(默认约定为 src/index.ts),识别注册的 MyComp 组合,在浏览器中打开本地开发服务器,支持逐帧拖动时间线、缩放画面、查看当前帧的 props 与渲染日志。任何对 src/ 下文件的修改都会即时反映到预览中。
3. 渲染视频
npx remotion render
当项目中只有一个 Composition 时,无需指定组合即可直接渲染,输出默认落在 out/ 目录并以组合 id 命名(即 out/MyComp.mp4)。模板的渲染规格即上文表格:720p、30fps、60 帧。若以后 Root 中注册了多个组合,则需要显式指定目标:
npx remotion render MyComp out/my-video.mp4
即在组合 id 后跟一个自定义输出路径。npx remotion render 对应 CLI 层 packages/cli/src/render.tsx 的实现,渲染过程中 Remotion 会逐帧用无头浏览器截图、再交由内置合成器编码成视频文件。
4. 升级 Remotion 到最新版本
npx remotion upgrade
该命令会检查并升级 remotion 及相关包到当前最新版本,保证与新增的 Studio 功能、渲染修复保持同步。它同样作为脚本暴露在 package.json("upgrade": "remotion upgrade")。
四条命令与脚本的对应关系汇总如下:
| 用途 | README 命令 | 实际执行 |
|---|---|---|
| 安装依赖 | npm install |
npm 按 lockfile 安装 |
| 启动预览 | npm run dev |
remotion studio |
| 渲染视频 | npx remotion render |
remotion render |
| 升级框架 | npx remotion upgrade |
remotion upgrade |
| 代码质量检查 | (无) | npm run lint → eslint src && tsc |
npm run lint 是模板自带但 README 未列出的附加脚本:先对 src/ 执行 ESLint,再执行 TypeScript 编译检查,改动代码后建议先跑一遍它来兜底类型错误。
理解模板的工程配置三件套
除了业务源码,template-blank 还携带了三份关键工程配置,理解它们能帮你判断“这个空模板到底预装了什么”。
remotion.config.ts:CLI 全局配置
remotion.config.ts 是模板中唯一直接参与构建行为的配置文件,全文如下:
import { Config } from "@remotion/cli/config";
Config.setRspack(true);
Config.setVideoImageFormat("jpeg");
Config.setOverwriteOutput(true);
三个配置项的语义分别为:
Config.setRspack(true):显式启用 Rspack 作为 Studio 预览与打包(npm run build对应的remotion bundle)所依赖的 bundler;Config.setVideoImageFormat("jpeg"):将渲染中间帧的图像格式设为 JPEG(默认即为此值),这是素材不含透明通道时的常规选择;如果画面需要保留 Alpha 通道,则应改为"png";Config.setOverwriteOutput(true):输出文件已存在时直接覆盖,而不是报错或询问。
文件头部注释还点出了一个重要边界:当你改用 Node.js API(例如 @remotion/renderer 提供的 renderMedia)进行编程式渲染时,这份配置文件不会生效,选项必须直接作为参数传入 API。也就是说该配置只作用于 CLI 与 Studio 路径,packages/bundler 与 packages/renderer 的编程式调用不受其约束。
tsconfig.json:类型检查口径
tsconfig.json 采用 strict: true 的严格模式,模块相关配置为 "module": "Preserve" + "moduleResolution": "Bundler",jsx 为 react-jsx(无需手动 import React),并开启 noEmit(仅做类型检查)与 noUnusedLocals。值得注意的是 exclude 中排除了 remotion.config.ts——该文件由 @remotion/cli 在另一套编译上下文里加载,因此不参与 tsc 检查。
eslint.config.mjs:扁平化 ESLint 预设
eslint.config.mjs 只有两行,直接导出 @remotion/eslint-config-flat 提供的规则集:
import { config } from "@remotion/eslint-config-flat";
export default config;
这正是 Remotion 推荐的 ESLint 9 扁平配置方案,对应仓库中的 packages/eslint-config-flat 包。
从空画布开始:让 MyComponent 画出第一帧
模板唯一的“游戏规则”是:把视觉内容写进 MyComponent。把它的 return null 替换为任何 React 节点即可开始作画。下面是一段最常见的起步写法——一个随帧号移动的色块:
import { useCurrentFrame, useVideoConfig, AbsoluteFill } from "remotion";
export const MyComponent: React.FC = () => {
const frame = useCurrentFrame();
const { width } = useVideoConfig();
return (
<AbsoluteFill
style={{
justifyContent: "center",
alignItems: "center",
backgroundColor: "#1e293b",
}}
>
<div
style={{
width: 200,
height: 120,
borderRadius: 16,
backgroundColor: "#e11d48",
transform: `translateX(${(frame / 60) * (width - 200)}px)`,
}}
/>
</AbsoluteFill>
);
};
useCurrentFrame() 返回当前渲染帧号(0~59),useVideoConfig() 返回 Composition 上声明的 fps、width、height 等规格,AbsoluteFill 则提供一个铺满整个画布的容器。保存文件后切回 Remotion Studio,即可看到色块在两秒内从左向右滑过画面;再执行 npx remotion render,就能导出这段动画。
这也是“空模板适合 AI 协作开发”的原因——由于没有示例动画作为上下文干扰,把这份 Composition.tsx 的结构连同需求一起交给 AI,输出的代码会直接落在清晰的空画布上。
常见自定义:改时长、改画布、加属性
对空模板的日常改动集中在 Composition.tsx 的 Composition 属性上:
- 改时长:调整
durationInFrames,例如 30fps 下想要 10 秒视频就设为300; - 改清晰度与帧率:修改
width/height/fps,例如竖屏短视频可改为1080×1920; - 改组合 id:
id会出现在渲染命令与 Studio 地址中,改成语义化名称(如PromoVideo)后,渲染命令同步变为npx remotion render PromoVideo; - 给组合加 props:
Props目前是空类型。填入字段后配合calculateMetadata,即可实现“数据到达后再解析元数据”的流程。如果需要运行时校验,可以参考 template-helloworld 引入zod与@remotion/zod-types的做法(见其 package.json)。
另外,从 create-video 模板注册表 中 allowEnableTailwind: true 字段可见,template-blank 在脚手架初始化阶段允许叠加 Tailwind,对应的实现逻辑在 packages/create-video/src/add-tailwind.ts——如果你习惯用 Tailwind 写样式,可以在创建项目时就选择启用。
总结
template-blank 是 Remotion 生态里“最小但五脏俱全”的样本:registerRoot 完成注册链路,Root 汇集组合,Composition 声明规格,package.json 串联命令,remotion.config.ts 控制构建渲染行为。理解这五个部分,就等于掌握了任何 Remotion 项目的通用骨架。后续想要深入学习,可以沿着这条链路继续阅读仓库中的相关实现:入口注册机制见 packages/core/src/register-root.ts,组合声明的运行时行为在 packages/core/src 中,渲染命令与 Studio 命令的 CLI 入口分别在 packages/cli/src/render.tsx 与 packages/cli/src/studio.ts。
从一个只输出空白的组件到导出第一段成品视频,中间隔着的只有一条 npm run dev、一次 npx remotion render,以及你在 MyComponent 里写下的第一段 JSX。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00