如何把 Remotion 视频渲染项目从 SSR 迁移到客户端渲染?
2026/9/12 15:11:27 网站建设 项目流程

如何把 Remotion 视频渲染项目从 SSR 迁移到客户端渲染?

【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion

如果你有一个已经能跑通的 Remotion 视频渲染项目,现在想把渲染从 Node.js 服务端搬到浏览器里执行,需要完成三件事:确认浏览器环境可用、按文档要求修改现有代码中的全局 API 和媒体组件、然后用renderMediaOnWeb()发起渲染并验证结果。客户端渲染由@remotion/web-renderer包提供,API 自 v4.0.491 起稳定。它的渲染依赖 WebCodecs API,浏览器最低版本要求为:

浏览器最低版本
Chrome94+
Firefox130+
Safari26+

与 SSR 相比,客户端渲染不需要 Node 服务器或 Remotion Lambda,用 WebCodecs 加 Mediabunny 编码而不是 FFmpeg,且没有 bundling 步骤——渲染函数直接接收组件和配置。

迁移前先确认浏览器能否渲染

@remotion/web-renderer提供canRenderMediaOnWeb(),用于在实际渲染前检查配置是否可执行,文档明确说它适合向用户反馈浏览器兼容性和配置问题。安装@remotion/web-renderer后(安装方式见 包文档),可以用它做迁移前的第一道检查:

import {canRenderMediaOnWeb} from '@remotion/web-renderer'; const result = await canRenderMediaOnWeb({ container: 'mp4', videoCodec: 'h264', width: 1920, height: 1080, }); if (!result.canRender) { for (const issue of result.issues) { console.error(issue.message); } } else { console.log('Ready to render!'); console.log('Video codec:', result.resolvedVideoCodec); console.log('Audio codec:', result.resolvedAudioCodec); }

canRenderfalse时,issues数组里每一项都有typemessage。文档列出的问题类型包括webcodecs-unavailable(浏览器没有 WebCodecs API)、container-codec-mismatchinvalid-dimensions(H.264 和 H.265 要求宽高是 2 的倍数)、video-codec-unsupportedaudio-codec-unsupportedtransparent-video-unsupported(透明度需要 VP8 或 VP9)、webgl-unsupported(3D CSS transform 需要 WebGL)、output-target-unsupported。每一项的severity"error"(阻塞)或"warning"(非阻塞,例如已应用回退)。

按迁移指南修改现有代码

官方迁移文档列出了四类必须处理的代码差异。逐条修改即可,不需要重写项目结构。

1. 用useRemotionEnvironment()替换getRemotionEnvironment()

getRemotionEnvironment()是全局 API,当同一页面存在多个 Remotion 实例(比如页面上挂着<Player>)时可能冲突。改用useRemotionEnvironment()hook,它把环境信息限定在调用它的组件上下文里。返回值包括isStudioisRenderingisPlayerisReadOnlyStudio,以及自 v4.0.344 起的isClientSideRendering(标识当前是否处于客户端渲染上下文):

import React from 'react'; import {useRemotionEnvironment} from 'remotion'; export const MyComp: React.FC = () => { const {isStudio, isPlayer, isRendering, isClientSideRendering} = useRemotionEnvironment(); if (isClientSideRendering) { return <div>Client-side render</div>; } // ... return <div>Hello World!</div>; };

2. 用useDelayRender()替换全局delayRender()continueRender()cancelRender()

项目里如果有多个渲染同时发生、或同页存在<Player>,全局的delayRender()等函数可能互相冲突。useDelayRender()把这三个函数限定到单个 composition 作用域内,文档称其为推荐写法:

import {useDelayRender} from 'remotion'; const MyComp: React.FC = () => { const {delayRender, continueRender, cancelRender} = useDelayRender(); return <div>My component</div>; };

把组件里直接 import 的delayRendercontinueRendercancelRender全部替换为从 hook 解构出来的同名函数,调用处代码不需要改动。

3. 确保所有资源可通过 CORS 访问

这是 SSR 与客户端渲染最容易被忽略的差异:SSR 在 Node.js 进程中下载音视频资源,图片即使 tainted 也能截图;客户端渲染则强制 CORS,图片和 canvas 不允许 tainted。如果你的图片 URL 没有Access-Control-Allow-Origin响应头,渲染时会看到这样的报错(文档示例):

Could not draw image with src="https://example.com/image.png" to canvas: The image is tainted due to CORS restrictions. The server hosting this image must respond with the "Access-Control-Allow-Origin" header.

如果图片 URL 本身加载失败(例如 404),则报:

Could not draw image with src="https://example.com/image.png" to canvas: The image is in a broken state. This usually means the image failed to load - check that the URL is valid and accessible.

迁移时需要逐一核对项目中图片、字体等资源所在服务器的 CORS 配置;两种报错分别对应"服务器缺少 CORS 头"和"资源本身不可达"。

4. 媒体组件替换为@remotion/media<Video><Audio>

客户端渲染只支持@remotion/media包提供的<Video><Audio>。迁移文档要求把所有Html5VideoHtml5Audio<OffthreadVideo>标签替换掉,限制文档给出了明确对应关系:

  • <Html5Video><Video>
  • <Html5Audio><Audio>
  • <OffthreadVideo><Video>
  • <AnimatedEmoji>不支持 → 改用<Lottie>

替换示例:

import {Video} from '@remotion/media'; // 迁移前:<Html5Video src="https://example.com/video.mp4" /> // 迁移后: const MyComp: React.FC = () => { return <Video src="https://example.com/video.mp4" />; };

音频的捕获方式是:挂载的<Audio><Video>元素的声音会被采集、混音后写入输出视频的音轨(见 工作原理文档)。

另外注意一个 API 差异:客户端渲染中不能使用getInputProps()读取输入参数,必须通过renderMediaOnWeb()inputProps参数传入。

renderMediaOnWeb()发起渲染

代码改完后,把原来走@remotion/renderer的渲染调用替换为renderMediaOnWeb()。它直接接收 React 组件和 composition 配置,没有 bundling 步骤。官方文档示例:

import {renderMediaOnWeb} from '@remotion/web-renderer'; import {Video} from '@remotion/media'; const Component: React.FC = () => { return <Video src="https://remotion.media/video.mp4" />; }; const {getBlob} = await renderMediaOnWeb({ composition: { component: Component, durationInFrames: 100, fps: 30, width: 1920, height: 1080, id: 'my-composition', }, }); const blob = await getBlob();

composition必须包含idcomponentdurationInFramesfpswidthheight;如果提供calculateMetadata,则宽高帧率时长可以动态计算。把渲染结果落盘的文档示例(通过URL.createObjectURL触发浏览器下载):

const result = await renderMediaOnWeb({composition}); const blob = await result.getBlob(); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'video.mp4'; a.click();

默认输出容器是mp4(视频h264、音频aac);webm容器默认vp8+opus。渲染过程中可以用onProgress回调观察进度,它接收encodedFramesprogressrenderEstimatedTimedoneIn等字段。如果希望渲染时页面保持响应,保持默认pageResponsiveness: "medium"即可;要渲染速度优先可以传"disabled"

如何验证迁移成功

验证按文档给出的方式分三层:

  1. 渲染前canRenderMediaOnWeb()返回canRender: true,且没有severity: "error"的 issue;
  2. 渲染中/后renderMediaOnWeb()正常 resolve,getBlob()返回可下载的视频Blob;若出现第 3 节中的 CORS 报错,说明资源配置尚未改对;
  3. Studio 验证:从 v4.0.491 起 Remotion Studio 始终启用客户端渲染,使用 "Render in browser" 按钮即可在 Studio 里直接发起浏览器渲染,用于对照检查迁移后的 composition。

迁移后要清楚的限制

客户端渲染不是"同一套代码换个执行器"。由于浏览器无法直接截取视口,Remotion 是把元素按它在 DOM 中的位置手动绘制到 canvas 上,只有<canvas><img><video><svg>能原生捕获像素,其余样式用 Canvas 2D API 模拟,因此 只支持一个 CSS 子集。迁移后需要对照限制文档检查项目用到的样式,重点包括:

  • object-positionperspectivetransform-stylewriting-modebackdrop-filtermix-blend-mode均不支持;
  • z-index不支持,层级要靠 DOM 中元素从后往前的书写顺序控制;
  • filterblur()brightness()等函数支持,但Safari/WebKit 不支持 filters,需要滤镜效果时用 Chrome 或 Firefox;
  • box-shadow基础形态支持,inset阴影和 spread 半径不支持。

另有两条运行边界:客户端渲染没有多线程并发;渲染所在的浏览器标签页切到后台时requestAnimationFrame会被浏览器节流,Remotion 会用 Web Worker 定时器兜底继续渲染,但后台渲染会比前台慢,渲染期间最好保持标签页可见。

最后提醒一点:客户端渲染每次渲染都会发送一条遥测事件,即使没有设置 license key。这与服务端渲染的行为不同,迁移后请确认这一点对你的部署环境可接受(详见文档中的 Telemetry 章节)。

相关文档

  • 迁移指南
  • 客户端渲染工作原理
  • 客户端渲染限制
  • renderMediaOnWeb()API
  • canRenderMediaOnWeb()API

【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询