尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用 Next.js 与 Remotion 构建可编程视频 SaaS:template-next-pages 模板深度指南

用 Next.js 与 Remotion 构建可编程视频 SaaS:template-next-pages 模板深度指南 用 Next.js 与 Remotion 构建可编程视频 SaaStemplate-next-pages 模板深度指南【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion导读本模板仓库内路径 packages/template-next-pages是 Remotion 官方为「搭建可编程视频应用」准备的 Next.js 起步工程它选用 Next.jsPages RouterApp Router 版本对应 packages/template-next-app并预置了 remotion/player浏览器端实时预览与 remotion/lambdaAWS 无服务器渲染两套能力。读完本文你将掌握如何快速生成该模板、理解它的目录架构与渲染链路、读懂config.mjs/deploy.mjs的全部参数、把「前端表单 → Next.js API 路由 → Lambda 渲染 → 进度轮询 → 视频下载」这条 SaaS 视频生成管线完整跑通。一、模板定位一个开箱即用的视频生成 SaaS在 Remotion 官方脚手架create-video的模板注册表 packages/create-video/src/templates.ts 中该模板的登记信息如下cliIdnext-pages-dir即用--next-pages-dir参数创建仓库对应目录templateInMonorepotemplate-next-pages即当前阅读的目录类型type: video定位是“面向希望构建能生成视频的应用的人的推荐选择”。也就是说这个模板不是演示单个视频如何渲染而是演示一个完整的视频生成产品应该怎样组织代码浏览器里用remotion/player实时播放视频并把“输入参数如标题文本”作为inputProps传入点渲染按钮后由 Next.js API 路由调度remotion/lambda在 AWS 上后台渲染再轮询渲染进度、最终提供下载链接。一个值得注意的约束该模板显式关闭了 Tailwind 集成开关allowEnableTailwind: false在 packages/create-video/src/pkg-managers.ts 中对next、next-pages-dir等模板做了相同的排除处理样式体系走原生 CSS Modules避免脚手架额外注入样式配置。二、目录结构速览各模块各司其职packages/template-next-pages/ ├── src/ │ ├── pages/ # Next.js 页面与 API 路由Pages Router │ │ ├── index.tsx # 首页Player 预览 渲染控制台 │ │ ├── _app.tsx # 应用入口导入全局样式 │ │ └── api/lambda/ │ │ ├── render.ts # POST发起 Lambda 渲染 │ │ └── progress.ts # POST查询渲染进度 │ ├── components/ # 前端 UIRenderControls、按钮、进度条等 │ ├── helpers/ │ │ ├── api-response.ts # API 统一响应包装与错误处理 │ │ └── use-rendering.ts # 渲染状态机invoking→rendering→done/error │ ├── lambda/api.ts # 浏览器端调用 API 路由的封装 │ └── remotion/ # 视频端代码与 Remotion 的 Composition 注册 │ ├── index.ts # registerRoot │ ├── Root.tsx # Composition 注册处 │ └── MyComp/ # 示例视频 Main / NextLogo / Rings / TextFade ├── types/ │ ├── constants.ts # 合成参数时长/分辨率/帧率/Props schema │ └── schema.ts # API 请求/响应 schema ├── config.mjs # Lambda 部署与调用共享配置唯一事实源 ├── deploy.mjs # 部署函数、存储桶与 bundle 的脚本 ├── remotion.config.ts # Remotion 打包器配置 ├── next.config.js # Next.js 配置 ├── .env.example # AWS 密钥环境变量样例 └── vercel.json # Vercel 构建命令先部署再构建目录里最关键的架构决策是types/constants.ts承担“前后端唯一事实源”它导出 zod 的CompositionProps前端表单类型、API schema、Player 的inputProps、Lambda 渲染入参全部引用它避免三处各写一份类型而漂移。三、快速开始两种方式拿到工程模板工程自身位于 monorepo 的 packages/template-next-pages 目录下。要在自己的机器上建独立项目官方提供两条路径使用 GitHub 的 “Use this template” 把它克隆到自己的账号下然后安装依赖npm i直接用 Remotion 官方脚手架命令创建这也是模板注册表cliId: next-pages-dir的用法npx create-videolatest --next-pages-dir依赖清单可在 package.json 中查看运行时核心是remotion、remotion/player、remotion/lambda、next、react/react-dom、zod在 monorepo 内它们以workspace:*形式互相引用独立脚手架后会自动解析为发布版本。UI 辅助依赖还有remotion/google-fonts、remotion/shapes、remotion/paths。四、常用命令与脚本映射模板 README 给出的命令都可以在 package.json 的scripts中找到对应用途命令脚本/说明启动 Next.js 开发服务器npm run dev即next dev浏览器访问首页预览 Player打开 Remotion Studionpm run remotion或npx remotion studio单独在 Studio 中编辑/预览视频本地渲染视频npm run render或npx remotion render无需 AWS直接在本地用 Chromium 渲染升级 Remotionnpx remotion upgrade将remotion及remotion/*升级到最新版部署 Lambdanpm run deploy或node deploy.mjs部署函数、存储桶与 site bundle构建与静态启动npm run build/npm startnext build/next start此外 remotion.config.ts 对渲染器做了两项全局设置Config.setRspack(true)使用 Rspack 作为打包器Config.setVideoImageFormat(jpeg)让本地渲染的帧图片格式采用 JPEG体积更小、渲染更快。注意该文件内注释强调使用 Node.js API如 Lambda 的renderMediaOnLambda时配置文件不生效参数需直接传给 API。五、模板背后的渲染链路页面 → API → Lambda模板默认只渲染当前帧浏览器预览与完整云端渲染双模式。核心链路为index.tsx (Player 实时预览 表单修改 inputProps) │ └─ 点击 Render video └─ use-rendering.ts (状态机) └─ src/lambda/api.ts → POST /api/lambda/render └─ pages/api/lambda/render.ts └─ renderMediaOnLambda() [remotion/lambda] └─ 返回 { renderId, bucketName } └─ 每秒轮询 POST /api/lambda/progress └─ pages/api/lambda/progress.ts └─ getRenderProgress() └─ done → { url, size } → 提供下载按钮5.1 首页Player 与输入框共用同一份 Props在 src/pages/index.tsx 中text状态被useMemo转成inputProps既传给Player做实时预览也传给RenderControls发起渲染const [text, setText] useStatestring(defaultMyCompProps.title); const inputProps: z.infertypeof CompositionProps useMemo(() { return { title: text }; }, [text]); Player component{Main} inputProps{inputProps} durationInFrames{DURATION_IN_FRAMES} fps{VIDEO_FPS} compositionHeight{VIDEO_HEIGHT} compositionWidth{VIDEO_WIDTH} controls autoPlay loop initiallyMuted /Player直接把 Remotion 组件Main /当作 React 组件渲染进普通网页这正是 Remotion 官方推荐的实时预览体验由于Player 与云端渲染消费的是同一份inputProps所见即所得。5.2 渲染状态机四种状态驱动 UIsrc/helpers/use-rendering.ts 用一个可辨识联合类型表达状态init初始态等待用户输入invoking正在调用渲染接口rendering拿到renderId/bucketName已开始轮询进度done拿到产物url与体积sizeerror任一环节失败展示error.message。轮询部分use-rendering.ts是 while 循环每次调用getProgress()依据返回的判别字段进入error/done/progress分支progress 分支await wait(1000)后继续查询即每秒刷新一次进度。对应地RenderControls.tsx 根据状态切换 UIinit/invoking/error显示输入框与 “Render video” 按钮rendering/done显示 ProgressBar 与下载按钮。5.3 API 路由实现与统一响应包装模板把 API 的“校验 响应包装”抽象成一个高阶函数 executeApiexport const executeApi Res, Req extends ZodType(schema: Req, handler: (...) PromiseRes) async (req: NextApiRequest, res: NextApiResponseApiResponseRes) { try { const parsed schema.parse(req.body); // zod 校验请求体 const data await handler(req, parsed, res); res.status(200).json({ type: success, data }); } catch (err) { res.status(500).json({ type: error, message: (err as Error).message }); } };所有接口的响应统一为{ type: success, data } | { type: error, message }见 src/helpers/api-response.ts浏览器端封装 src/lambda/api.ts 据此做类型收窄type error时直接 throw。发起渲染src/pages/api/lambda/render.ts 关键参数const result await renderMediaOnLambda({ codec: h264, functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, timeoutInSeconds: TIMEOUT, }), region: REGION as AwsRegion, serveUrl: SITE_NAME, // 指向部署的 site bundle 名 composition: body.id, // 要渲染的 Composition id inputProps: body.inputProps, // 标题文本等 framesPerLambda: 10, downloadBehavior: { type: download, fileName: video.mp4 }, });注意functionName不是硬编码而是通过speculateFunctionName()根据DISK/RAM/TIMEOUT计算——这保证了API 路由找到的正是deploy.mjs部署出来的那个函数二者永远使用同一份config.mjs修改配置后只要重新部署即可保持一致。查询进度src/pages/api/lambda/progress.ts 调用getRenderProgress()把低层状态翻译成前端友好的三态fatalErrorEncountered→{ type: error, message }done→{ type: done, url, size }否则 →{ type: progress, progress: Math.max(0.03, overallProgress) }下限 0.03保证进度条不会停留在 0 造成“没反应”的错觉。请求与响应的 zod schema 集中在 types/schema.tsRenderRequest校验{ id, inputProps }ProgressRequest校验{ bucketName, id }。六、视频端Composition 注册与示例动画Remotion 侧入口 src/remotion/index.ts 调用registerRoot(RemotionRoot)Root.tsx 注册了两个 CompositionMyComp1280×720、30fps、200 帧即主示例视频NextLogo140×140、300 帧Logo 独立动画。参数常量集中在 types/constants.tsCOMP_NAME MyComp、DURATION_IN_FRAMES 200、VIDEO_WIDTH 1280、VIDEO_HEIGHT 720、VIDEO_FPS 30Props schema 为{ title: string }默认标题 “Next.js and Remotion”。示例视频本体 src/remotion/MyComp/Main.tsx 是一段很典型的 Remotion 动画代码用spring驱动 Logo 退场damping: 200delay从2 * fps帧开始用两个Sequence控制“Logo/光环”与“标题淡入”的时间轴字体来自remotion/google-fonts/Inter的loadFont()400/700 字重。标题文字的“擦除式”进场由 TextFade.tsx 实现——它把spring进度经interpolate映射为 mask 渐变的左右端点产生从左到右渐显的动效。这一整块src/remotion正是「改变视频模板后需要重新部署 bundle」的那部分代码与后面的部署流程直接相关。七、config.mjsLambda 渲染的共享配置config.mjs 是整个云端渲染的“唯一事实源”导出 5 个值变量默认值含义REGIONus-east-1AWS 区域编辑器可提示全部合法值AwsRegion类型SITE_NAMEmy-next-appsite bundle 在存储桶中的名称也是serveUrlRAM3009Lambda 内存MBDISK10240Lambda/tmp磁盘MB即 10 GBTIMEOUT240单次函数调用超时秒RAM、DISK、TIMEOUT三个值会在deploy.mjs的deployFunction()和 API 路由的speculateFunctionName()两处同时使用前者按此规格创建函数后者据此推导函数名。因此若直接修改config.mjs必须重新运行部署脚本保证实际函数规格与函数名同步更新。八、deploy.mjs一键完成“函数 存储桶 Bundle”部署deploy.mjs 依次执行三件事deployFunction({ createCloudWatchLogGroup: true, memorySizeInMb: RAM, region: REGION, timeoutInSeconds: TIMEOUT, diskSizeInMb: DISK })—— 创建或复用渲染函数输出函数名与(created)/(already existed)getOrCreateBucket({ region })—— 创建或复用S3 存储桶Lambda 渲染的中间产物与最终视频都存放在此deploySite({ bucketName, entryPoint: path.join(process.cwd(), src, remotion, index.ts), siteName: SITE_NAME, region: REGION })—— 将src/remotion/index.ts作为入口打包并上传 bundle。脚本开头会做环境变量守卫deploy.mjs若同时缺失AWS_ACCESS_KEY_ID/REMOTION_AWS_ACCESS_KEY_ID及对应的 secret 变量则提示先去完成 Lambda 设置并以退出码 0 结束而不是在未配置密钥时报晦涩的 AWS 错误。运行node deploy.mjs或npm run deploy。README 特别提醒以下三种变更之后都应重跑该脚本修改了视频模板src/remotion下的 Composition 代码修改了config.mjs区域、内存、超时、site 名等将 Remotion 升级到了新版本。这也与脚本结尾的提示文案一一对应deploy.mjs。九、启用 AWS Lambda 云端渲染三步走复制环境变量样例并填充密钥将 .env.example 复制为.envREMOTION_AWS_ACCESS_KEY_ID REMOTION_AWS_SECRET_ACCESS_KEY在 AWS 上完成 IAM/凭据开通后填入这两个变量。.env*.local已被 .gitignore 忽略密钥不会进入版本库。deploy 脚本与 API 路由render.ts同时兼容AWS_*与REMOTION_AWS_*两种变量名并给出缺失时的中文指引式报错。按需编辑config.mjs的区域、内存与超时等参数。运行node deploy.mjs脚本会创建渲染函数与存储桶并上传 bundle直到输出 “You now have everything you need to render videos!”。如果你计划把前端部署到 Vercel模板自带的 vercel.json 已把构建命令设为node deploy.mjs next build——即在构建前端之前先确保云端函数与 bundle 就绪避免线上访问渲染接口时发现函数尚未创建。十、本地渲染与 Studio不需要 AWS 也能出片云端渲染适用于生产环境日常开发迭代可以用两种本地方式npx remotion studio打开 Remotion Studio逐帧编辑动画、调试合成参数时长/尺寸/帧率在 types/constants.ts 修改npx remotion render在本地用无头 Chromium 直接输出 MP4适合 CI 与无 AWS 环境下的快速验证。前端、Studio、本地渲染、Lambda 渲染复用同一套 Composition 代码与常量定义这也是本模板前后端一致的架构基础。十一、小结模板给你划好的三条边界读完本模板能清晰看到 Remotion 官方对“视频生成 SaaS”推荐的工程边界视频内容与产品解耦src/remotion只负责“画面”通过 zod Props 与外部交互替换业务视频只需改这个目录并重跑node deploy.mjs前端与渲染解耦Next.js API 路由薄薄一层负责鉴权/参数校验/调度云端渲染细节收敛在remotion/lambda配置集中config.mjs.env分别管理非敏感参数与密钥deploy.mjs与 API 路由永远基于同一份配置推导函数名与参数避免“部署 A 规格、调用 B 规格”的错位。License 方面Remotion 对部分实体企业使用另有要求详见仓库根目录 LICENSE.md。【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表