使用 Remotion + Next.js App Router 构建可编程视频应用:template-next-app-tailwind 模板完整指南
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
本指南围绕 Remotion 官方 Next.js 模板template-next-app-tailwind展开,讲解如何在 Next.js(App Router + TailwindCSS)应用中嵌入@remotion/player实时预览视频,并借助@remotion/lambda把视频渲染放到 AWS Lambda 上按需执行。读完本文你将掌握:模板的目录结构、五大核心命令、前后端共享的类型设计、Play 组件嵌入方式,以及从本机渲染到云端无服务器出片的完整链路,可直接在真实项目中照抄落地。
模板定位:面向"程序化视频应用"的一体化起点
packages/template-next-app-tailwind是 Remotion 官方为构建程序化视频(programmatic video)应用而设计的 Next.js 模板。所谓程序化视频应用,典型形态是一个 Web 页面:用户在浏览器里编辑文案/参数 → 页面内的播放器实时预览合成 → 点击渲染按钮 → 服务器通过 API 调用远程渲染 → 返回视频文件链接供用户下载。
这一模板恰好把该链路的三个关键拼图集成在同一个工程中:
- Remotion 视频合成:用 React 组件描述视频画面(见
src/remotion/目录); @remotion/player:把合成视频当作一个可交互的 HTML 播放器嵌入到 Next.js 页面中,实现零等待的实时预览;@remotion/lambda:把"渲染视频"这一计算密集型任务分发到 AWS Lambda 执行,避免在 Node.js 服务端做重负载渲染。
在技术选型上,模板明确使用Next.js App Router + TailwindCSS。如果你需要其他形态,本仓库(monorepo)中还有两个等价变体可对照参考:不使用 Tailwind 的 App Router 版本 template-next-app,以及 Pages Router 版本 template-next-pages。
技术栈与依赖
从 package.json 可以看到模板的完整技术栈:
- 框架层:
next@16.2.11、react@19.2.3、react-dom@19.2.3; - Remotion 核心:
remotion、@remotion/cli、@remotion/bundler、@remotion/player、@remotion/lambda、@remotion/google-fonts、@remotion/paths、@remotion/shapes; - 样式:
tailwindcss@4.2.0+@tailwindcss/postcss,以及 Remotion 侧集成 Tailwind 用的@remotion/tailwind-v4; - 类型校验:
zod@4.5.4,用于跨前后端共享 props 的 schema; - 工具:
clsx、tailwind-merge(src/lib/utils.ts中通常用它们封装 className 合并)。
目录结构速览
src/ app/ api/lambda/render/route.ts # 触发渲染的 API 路由(POST) api/lambda/progress/route.ts # 查询渲染进度的 API 路由(POST) layout.tsx / page.tsx # 首页:内嵌 Player + 渲染控制 components/ # 页面 UI:RenderControls、ProgressBar 等 helpers/use-rendering.ts # 前端渲染状态机 + 轮询逻辑 lambda/api.ts # 前端调用后端 API 的封装 lib/utils.ts remotion/ index.ts # Remotion 打包入口(deploy 时指定) Root.tsx # 注册 Composition MyComp/ # 示例合成:Main/NextLogo/Rings/TextFade webpack-override.mjs # 让 Tailwind 样式进入 Remotion 打包 types/ constants.ts # 共享常量 + zod schema schema.ts # API 请求/响应 schema config.mjs # Lambda 部署参数集中配置 deploy.mjs # 一键部署 Lambda 函数、S3 Bucket、站点 remotion.config.ts # Remotion 打包配置(Rspack + JPEG)快速开始:三种初始化方式
模板的 README 给出两条上手路径,任选其一:
方式一:GitHub 模板仓库克隆,进入目录后安装依赖:
npm i方式二:使用create-video脚手架一键生成:
npx create-video@latest --next-tailwind这条命令会在交互式引导下直接生成一个与当前仓库等价的 Next.js + Tailwind 工程。之后启动开发环境:
npm run dev在浏览器打开本地地址即可看到首页:页面中通过@remotion/player渲染了一段示例合成动画,并带有文字输入框与"渲染"控制面板。任何一次改动(例如修改输入文字),播放器都会即时反映——这正是把视频"组件化 + 实时预览"带入 Web 应用的核心体验。
五大常用命令详解
模板在 package.json 中预置了脚本,同时也支持直接调用 Remotion CLI。下表汇总了开发与部署中最常用的操作:
| 目的 | 命令 | 说明 |
|---|---|---|
| 启动 Next.js 开发服务器 | npm run dev | 等价于next dev |
| 打开 Remotion Studio | npm run remotion | 等价于npx remotion studio,可逐帧调试合成 |
| 本地渲染视频 | npm run render | 等价于npx remotion render |
| 升级 Remotion | npx remotion upgrade | 将项目内的 Remotion 相关包升级到一致版本 |
| 部署到 AWS Lambda | npm run deploy | 等价于node deploy.mjs,见下文 |
其中 Studio 与本地渲染属于"在开发机上直接出片"的场景:npx remotion studio会打开图形化界面,逐帧预览、拖动时间线、调整输入 props;npx remotion render则使用当前remotion.config.ts与本机环境渲染视频文件。
在 Next.js 页面中嵌入播放器:@remotion/player
首页 src/app/page.tsx 展示了 Player 的典型用法。核心代码:
"use client"; import { Player } from "@remotion/player"; import { useMemo, useState } from "react"; import { z } from "zod"; import { Main } from "../remotion/MyComp/Main"; import { RenderControls } from "../components/RenderControls"; // ... 其他导入 const Home: NextPage = () => { const [text, setText] = useState<string>(defaultMyCompProps.title); const inputProps: z.infer<typeof CompositionProps> = useMemo(() => { return { title: text }; }, [text]); return ( <div> <div className="max-w-screen-md m-auto mb-5 px-4"> <Player component={Main} inputProps={inputProps} durationInFrames={DURATION_IN_FRAMES} fps={VIDEO_FPS} compositionHeight={VIDEO_HEIGHT} compositionWidth={VIDEO_WIDTH} style={{ width: "100%" }} controls autoPlay loop initiallyMuted /> <RenderControls text={text} setText={setText} inputProps={inputProps} /> <Tips /> </div> </div> ); };几个值得注意的要点:
component={Main}直接传入 Remotion 的合成组件(而非字符串 ID),这是 Player 与 Studio 渲染的最大区别——不需要经过打包即可在浏览器内渲染;- 尺寸三件套:
compositionWidth/compositionHeight为画布逻辑尺寸(本例 1280×720),实际页面宽度由 CSS 决定,代码注释特别提醒:播放器自带样式的优先级高于 Tailwind class,因此这里用内联style={{ width: "100%" }}来铺满容器; inputProps即用户输入到视频的数据,与输入框的useState联动,实现"改文字即改视频";- 播放控制:
controls显示控制条,autoPlay/loop/initiallyMuted让预览体验接近成品视频; - 页面根布局 layout.tsx 导入全局样式
styles/global.css,其中定义了bg-background等 Tailwind 主题 token。
合成组件与共享类型:一处定义、三端复用
模板的巧妙之处在于把视频的参数类型集中在一处,供 Remotion 打包、Player 预览、后端 API 三处共享。
常量与 zod Schema
types/constants.ts 定义了合成名、参数 schema 与画布规格:
import { z } from "zod"; export const COMP_NAME = "MyComp"; export const CompositionProps = z.object({ title: z.string(), }); export const defaultMyCompProps: z.infer<typeof CompositionProps> = { title: "Next.js and Remotion", }; export const DURATION_IN_FRAMES = 200; // 总时长 200 帧 export const VIDEO_WIDTH = 1280; // 横向 16:9 export const VIDEO_HEIGHT = 720; export const VIDEO_FPS = 30; // 帧率 30fpsz.object定义 props 类型后,z.infer<typeof CompositionProps>可以把TypeScript 类型直接推导出来,前端useState、API 入参都能引用它,彻底消除"类型漂移";- 帧数换算时长:200 帧 ÷ 30fps ≈ 6.67 秒。
注册合成
src/remotion/Root.tsx 是 Remotion 的组件注册表,声明了示例中实际存在的两个合成:
<Composition id={COMP_NAME} // "MyComp" component={Main} durationInFrames={DURATION_IN_FRAMES} // 200 fps={VIDEO_FPS} // 30 width={VIDEO_WIDTH} // 1280 height={VIDEO_HEIGHT} // 720 defaultProps={defaultMyCompProps} /> <Composition id="NextLogo" component={NextLogo} durationInFrames={300} fps={30} width={140} height={140} defaultProps={{ outProgress: 0 }} />示例合成组件位于 src/remotion/MyComp/(Main.tsx、NextLogo.tsx、Rings.tsx、TextFade.tsx),入口文件 src/remotion/index.ts 同时是deploy.mjs上传到 S3 的打包入口。若新增视频模板,只需按同样模式:写组件 → 在Root.tsx注册Composition→ 在types/constants.ts维护 props schema。
本机渲染体验:Studio 与 CLI
在无需云端的场景下,开发阶段可以直接在本机渲染:
npx remotion studio # 打开 Remotion Studio 图形界面 npx remotion render # 依据 remotion.config.ts 在本机渲染默认合成渲染行为由根目录的 remotion.config.ts 控制:
import { Config } from "@remotion/cli/config"; import { webpackOverride } from "./src/remotion/webpack-override.mjs"; Config.setRspack(true); // 启用 Rspack 作为打包器 Config.setVideoImageFormat("jpeg"); // 视频帧编码使用 JPEG Config.overrideBundlerConfig(webpackOverride);setRspack(true)让 Remotion 使用基于 Rust 的 Rspack 打包器,提高打包与预览速度;overrideBundlerConfig(webpackOverride)把 Tailwind v4 的 PostCSS 处理接进 Remotion 的打包流程,使Composition内也能使用 Tailwind 类(实现见 webpack-override.mjs)。
需要指出的是:该配置文件只对CLI / Studio生效。使用 Node.js API(例如@remotion/renderer或@remotion/lambda)时,应把相应选项直接作为 API 参数传入。
基于 AWS Lambda 的无服务器渲染链路
这是模板价值最高的部分:把渲染从开发机搬到 AWS。整条链路为——浏览器按钮 → Next.js API 路由 →renderMediaOnLambda提交渲染任务 → 轮询getRenderProgress→ 完成后返回可下载的视频 URL。
第一步:集中配置 Lambda 参数
config.mjs 是唯一需要人工编辑的部署配置文件:
/** * Use autocomplete to get a list of available regions. * @type {import('@remotion/lambda').AwsRegion} */ export const REGION = "us-east-1"; export const SITE_NAME = "my-next-app"; export const RAM = 3009; // Lambda 内存(MB) export const DISK = 10240; // /tmp 磁盘(MB) export const TIMEOUT = 240; // 超时(秒)各参数的语义与影响:
| 参数 | 默认值 | 说明 |
|---|---|---|
REGION | us-east-1 | AWS 区域,编辑器会提供AwsRegion类型补全 |
SITE_NAME | my-next-app | 部署到 S3 的站点名(serveUrl),也用于 API 引用 |
RAM | 3009 | Lambda 函数内存;直接影响并发渲染能力与费用 |
DISK | 10240 | Lambda 临时磁盘/tmp上限(MB),复杂合成需更大空间 |
TIMEOUT | 240 | 单个 Lambda 渲染任务允许运行的最大秒数 |
deploy.mjs与两个 API 路由均从该文件读取配置,因此修改参数后必须重新部署(README 明确要求)。
第二步:填充 AWS 凭证
按 README 步骤:
- 将
.env.example(本模板中真实存在)复制为.env并填入你的 AWS 凭证; - 参照 Remotion 官方的 Lambda setup 指南完成 AWS 侧初始化(创建 IAM 用户、授予权限等),获得
AWS_ACCESS_KEY_ID与AWS_SECRET_ACCESS_KEY。
从 deploy.mjs 的凭证检查逻辑可以看到,它同时兼容两组环境变量命名,方便你在既有 AWS SDK 命名与 Remotion 命名之间选择:
AWS_ACCESS_KEY_ID或REMOTION_AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY或REMOTION_AWS_SECRET_ACCESS_KEY
如果凭证缺失,脚本不会直接失败,而是打印提示并process.exit(0)退出,说明"Lambda 渲染未配置"。
第三步:执行 deploy.mjs
node deploy.mjs脚本依次完成三件工作(内部使用@remotion/lambda的 API):
deployFunction:部署/复用渲染函数,createCloudWatchLogGroup: true便于在 CloudWatch 查日志,内存、超时、磁盘均取自config.mjs,返回functionName及是否已存在;getOrCreateBucket:在指定区域确保渲染用的 S3 Bucket 存在(不存在则创建),返回bucketName;deploySite:把 Remotion 合成(入口src/remotion/index.ts)打包并上传为站点,options: { webpackOverride }保证 Tailwind 样式被正确打包。
部署成功后终端会提示"You now have everything you need to render videos!"。README 同时强调:在以下三种情况后都应重新运行node deploy.mjs:
- 修改了视频模板(
src/remotion/下的组件与合成); - 修改了
config.mjs中的参数; - 把 Remotion 升级到了新版本。
第四步:两个 API 路由串联渲染与进度查询
前端不直接持有 AWS 密钥,而是通过 Next.js API 路由中转。前端封装见 src/lambda/api.ts:renderVideo()向/api/lambda/render发起 POST,getProgress()向/api/lambda/progress发起 POST,二者统一解析{ type: "error" }响应并抛错。
触发渲染:/src/app/api/lambda/render/route.ts 校验凭证后调用核心 API:
const result = await renderMediaOnLambda({ codec: "h264", functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, timeoutInSeconds: TIMEOUT, }), region: REGION as AwsRegion, serveUrl: SITE_NAME, composition: body.id, inputProps: body.inputProps, framesPerLambda: 10, downloadBehavior: { type: "download", fileName: "video.mp4", }, });其中speculateFunctionName()依据config.mjs的三项参数推断出函数名——这正是"改了 config 必须重跑 deploy"的原因:函数名由这些参数决定,参数变化即意味着函数需要重新创建。framesPerLambda: 10表示每个 Lambda 实例负责渲染 10 帧,控制单任务粒度与并发拆分;downloadBehavior让产物以附件形式下载并命名为video.mp4。
查询进度:/src/app/api/lambda/progress/route.ts 调用getRenderProgress,并把三态结果映射给前端:
- 遇
fatalErrorEncountered→ 返回{ type: "error", message: errors[0].message }; - 渲染完成 → 返回
{ type: "done", url, size }; - 进行中 → 返回
{ type: "progress", progress: Math.max(0.03, renderProgress.overallProgress) },0.03下限保证进度条起步可见。
请求体与响应均以 types/schema.ts 中的 zod schema 为准(RenderRequest、ProgressRequest与三态ProgressResponse),两个路由通过src/helpers/api-response.ts暴露的executeApi包装器完成校验与统一响应格式。
第五步:前端的渲染状态机与轮询
src/helpers/use-rendering.ts 实现了完整的渲染生命周期管理,用一个判别联合类型描述状态:
init → invoking → rendering(含 progress)→ done | error核心流程为:点击渲染后先置invoking并调用renderVideo拿到renderId与bucketName,随后进入while (pending)轮询循环——每隔1 秒(await wait(1000))调用一次getProgress,根据返回的三态推进 UI;出错时记录error,完成时保存url与文件size,并通过undo()一键回到初始态。配套的ProgressBar、RenderControls、DownloadButton等组件(见src/components/)把上述状态渲染为进度条、错误提示与下载按钮。
部署到 Vercel 时的构建链
由于vercel.json的存在,本模板可被 Vercel 直接识别:
{ "buildCommand": "node deploy.mjs && next build" }也就是说,Vercel 云端构建时会先执行 Lambda 部署脚本、再执行 Next.js 构建。要让它顺利通过,必须在 Vercel 的项目环境变量中配置好 AWS 凭证(即REMOTION_AWS_ACCESS_KEY_ID/REMOTION_AWS_SECRET_ACCESS_KEY)。这保证了"前端域名上线时,渲染后端也总是处于已部署状态"。
常见误区与注意事项
综合 README 与源码中的检查逻辑,实践中有几条高频坑点需要规避:
- 改完
config.mjs忘了重跑deploy.mjs:speculateFunctionName基于内存/磁盘/超时推断函数名,deploySite上传的是旧站点,渲染极可能报"找不到函数/站点"; - 只在
.env填了一组凭证,却用了另一组命名:deploy 与 render 路由分别兼容AWS_*与REMOTION_AWS_*两套变量名,请保持一致; - 在 Node.js API 中使用
remotion.config.ts:该文件只作用于 CLI/Studio,Lambda 渲染参数必须显式传入renderMediaOnLambda(模板正是这么做的); - 升级 Remotion 版本:升级后应重跑
node deploy.mjs,否则云端函数与本地版本不匹配可能导致兼容性错误。
进一步探索
- 对照非 Tailwind 的 App Router 版本:template-next-app;对照 Pages Router 版本:template-next-pages;
- 若想脱离模板理解底层,可阅读 Remotion Lambda 的客户端 SDK 与类型定义:
packages/lambda、packages/lambda-client,以及播放器内核 packages/player; - 模板使用与许可证以仓库根目录 LICENSE.md 为准(README 也提示:部分实体公司可能需要购买商用许可)。
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考