
Remotion remotion/player 本地测试床实战从 bun 启动命令到 Player API 全量演练【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion本篇技术文章以仓库中 SKILL.md 定义的工作流为主线讲解如何在 Remotion 单体仓库中准备环境、启动 packages/player-example 的remotion/player示例应用并在浏览器中打开http://localhost:3000。读完本文你将掌握该测试床的完整启动步骤、页面路由结构以及测试床内部对Player组件 props、PlayerRef方法、事件系统与自定义控件/缩略图 API 的全量演练方式。这个技能文档定义了怎样的工作流SKILL.md 是为 Agent 编写的操作技能skill其用途描述为“启动remotion/player示例应用并在 Codex 浏览器中打开它”。文档给出了一条五步工作流在仓库根目录执行bun i bun run build安装依赖并构建整个 monorepo进入示例包目录启动开发服务器cd packages/player-example bun run dev保持服务器进程运行并读取其输出中的本地 URL。文档指出默认预期地址是http://localhost:3000但若 Next.js 选择了其他端口应以终端实际打印的 URL 为准在内置浏览器中打开该 URL向用户告知 player example 的访问地址并说明这是新启动的服务器还是此前已在运行的服务器。这个流程看似简单但它触及了 Remotion monorepo 的两个关键机制示例包依赖workspace:*内部包必须先构建以及 Next.js 开发服务器的动态端口行为。下面结合仓库源码逐一展开。环境准备为什么必须先 bun i bun run build技能文档第一步要求先执行bun i bun run build原因在于 packages/player-example/package.json 的依赖结构remotion/player、remotion、remotion/bundler、remotion/canvas、remotion/google-fonts、remotion/preload、remotion/gif、remotion/media等核心包全部以workspace:*的形式引用即指向 monorepo 内的本地源码包如 packages/player。这些包的产物需要先通过 monorepo 根目录的构建流程生成。查看仓库根目录 package.json 可以确认对应关系build: turbo run make --no-update-notifier——bun run build实际是通过 Turbo 对各个包执行make任务根脚本还提供了更细粒度的变体例如makeplayer: turbo run make --filterremotion/player和watchplayer: turbo watch make --filterremotion/player前者只构建 Player 包后者在开发 Player 包本身时可用 watch 模式持续重建仓库声明了packageManager: bun1.3.3说明官方工具链是 Bun这也是技能文档使用bun i而非npm install的原因依赖版本通过workspaces.catalog统一管理其中react为19.2.3、next为16.2.11——这解释了示例包中catalog:版本号的实际取值。因此“先构建、再启动”的顺序是硬约束跳过bun run build时workspace:*依赖包没有构建产物next dev会因解析不到产物而失败。启动 player-exampledev 脚本与端口约定第二步cd packages/player-example bun run dev对应 package.json 中的三个脚本脚本命令用途devnext dev启动 Next.js 开发服务器日常调试使用build-sitenext build构建静态站点testnextjsnext build被根目录turbo run testnextjs调用的 CI 校验任务验证该示例能在 Next.js 构建中通过技能文档特别强调“预期默认是http://localhost:3000但要以打印出的 URL 为准”——这是 Next.js 的标准行为当 3000 端口被占用时next dev会自动顺延到 3001、3002 等端口并在终端输出Ready on http://localhost:300x。文档同时要求保持该进程持续运行dev 服务器是前台进程不能像一次性构建那样结束并区分“新启动”与“已在运行”两种状态避免对同一个示例端口重复起服务。页面路由一个多场景的 Player 演示站启动后打开首页会看到 pages/index.tsx 渲染的路由索引页列出了 8 个聚焦场景每个都是pages/目录下的一个独立页面路由页面文件演示内容/playerpages/player.tsx主测试床带自定义控件面板的 Player 与 Thumbnail/canvaspages/canvas.tsx挂载中的时间轴层实时列表/audiopages/audio.tsx在含音频的合成之间切换/audio-switchingpages/audio-switching.tsx切换合成与预取的音频源/autoplay-muted-videopages/autoplay-muted-video.tsx静音自动播放视频/autoplay-unmuted-videopages/autoplay-unmuted-video.tsx演练浏览器自动播放拦截与回退行为/fullscreenpages/fullscreen.tsx占满浏览器视口的 Player/video-ssrpages/video-ssr.tsx通过 Next.js 服务端渲染输出视频 Player/issue-7183pages/issue-7183.tsxPlayer 在 3D 变换父元素内的测量问题复现这个路由组织方式本身值得借鉴每个页面验证一个特定的 Player 边界行为自动播放策略、SSR 兼容、3D 变换下的尺寸测量、音频切换而不是把所有功能堆在一个页面里。全局样式方面pages/_app.tsx 仅引入了一份 fullscreen.css 用于全屏场景。主测试床 App.tsxPlayerRef 方法与事件系统全量演练/player页面是核心它渲染 src/App.tsx 导出的App组件并传入合成组件CarSlideshow与durationInFrames{500}。App由两部分组成PlayerOnly负责渲染Player和ControlsOnly负责一整套交互按钮。这两部分合在一起实际上就是一份remotion/playerAPI 的可执行清单。Player 组件的核心 propsPlayerOnly中的Player用法App.tsx 第 648–690 行附近覆盖了这些关键 propsPlayer ref{playerRef} controls acknowledgeRemotionLicense compositionWidth{1920} compositionHeight{1080} fps{30} component{CarSlideshow} // 或 lazyComponent 懒加载形式 durationInFrames{500} loop{loop} clickToPlay{clickToPlay} doubleClickToFullscreen{doubleClickToFullscreen} spaceKeyToPlayOrPause{spaceKeyToPlayOrPause} moveToBeginningWhenEnded{moveToBeginningWhenEnded} playbackRate{playbackRate} inputProps{inputProps} initialFrame{30} showPosterWhenUnplayed{...} showPosterWhenBuffering{...} showPosterWhenBufferingAndPaused{...} showPosterWhenEnded{...} showPosterWhenPaused{...} inFrame{inFrame} outFrame{outFrame} alwaysShowControls{alwaysShowControls} showVolumeControls{showVolumeControls} showPlaybackRateControl{showPlaybackRateControl} hideControlsWhenPointerDoesntMove{...} renderLoading{renderLoading} renderPoster{renderPoster} errorFallback{errorFallback} /几个值得注意的实现细节合成组件支持两种注入方式。CompProps类型定义了component直接传入或lazyComponent返回Promise{default: Component}二选一测试床两种模式都可通过不同页面复用同一个AppinputProps是响应式的。标题、文字颜色、背景色来自 React state通过useMemo组装后传给 Player修改输入框会实时驱动合成内容变化——这正是remotion/player与渲染服务最大的差异合成是“活的”renderLoading/renderPoster/errorFallback三个自定义回调分别演示了加载态黄色底 Loading动画文案 “Loading for 3 seconds...”、海报态区分isBuffering显示 “Buffering” 或 “Click to play”和错误兜底Sorry about this! An error occurred: {error.message}inFrame/outFrame用于裁剪播放区间界面上通过两个可启用的滑块取值范围0到durationInFrames演示如何限制 Player 只播放某一段Player 的style设置了resize: both、maxWidth/maxHeight: 550、minWidth/minHeight: 300让用户可以直接拖拽调整 Player 尺寸来验证响应式缩放。PlayerRef 命令式方法ControlsOnly中通过useRefPlayerRef(null)拿到实例后演练了这些命令式 API方法界面对应按钮play(e)▶️ Play传入事件对象以支持自动播放策略pause()⏸️ Pausetoggle()⏯️ ToggleseekTo(frame)seekTo 10 and pause / seekTo 50 / 5 seconds forwardseekTo(getCurrentFrame() fps * 5)越界 seekseekTo(10000)与seekTo(-10000)验证边界外帧号的处理mute()/unmute()/setVolume(v)静音、取消静音、音量 0 / 0.5 / 1getCurrentFrame()/isMuted()/getVolume()写入日志面板的只读查询inputProps相关的三个属性title、color、bgColor通过顶部的文本输入框和两个input typecolor颜色选择器实时修改演示了 Player 对 props 变更的热更新能力。事件系统13 种 Player 事件ControlsOnly的useEffect中注册了完整的事件监听清单每个事件触发时都向日志面板追加一行带时间戳的记录并在组件卸载时逐一removeEventListener清理play、pause、seeked含e.detail.frame、ended、error、timeupdatee.detail.frame、frameupdatee.detail.frame、ratechangee.detail.playbackRate、scalechangee.detail.scale、volumechangee.detail.volume、mutechangee.detail.isMuted、fullscreenchangee.detail.isFullscreen、waiting、resume。日志面板只保留最近 10 条logs.slice(0).reverse().slice(0, 10).reverse()。这种“事件 → 日志”的映射方式是调试 Player 时序问题的有效模板你能直观看到一次 seek 会先触发哪个事件、暂停期间timeupdate是否还在派发等。合成主体 CarSlideshow 与自定义控件CarSlideshow被播放器驱动的合成/player页面传入的合成为 src/CarSlideshow.tsx。它展示了 Player 与 Remotion 核心 API 的配合通过useCurrentFrame()与useVideoConfig()读取当前帧和{width, height, durationInFrames}再用interpolate(frame, [0, durationInFrames], [width, width * -1])让标题文字从右向左横穿画面staticFile(/logo.png)加载静态资源对应 public/logo.png第 10 帧起通过Sequence from{10}挂载一段远程Html5Video视频源用于在 Player 中验证视频元素的播放行为一个隐藏的“错误触发器”模块级playerExampleCompref 通过useImperativeHandle暴露triggerError()调用后合成内部抛出Error(some error)——这正是主测试床上 “trigger error” 按钮的后端用来验证errorFallback兜底 UI 是否生效。CustomControlsExamplerenderCustomControls 的位置src/CustomControlsExample.tsx 演示了renderCustomControlsprop它接收PlayerRef监听play/pause事件维护按钮文案Custom Play / Custom Pause点击时调用toggle()。页面注释说明了该自定义控件的渲染位置——位于主控件区与全屏按钮之间适合放置“重播”“字幕开关”等业务按钮。Thumbnail静态帧的另一面pages/player.tsx 页面还渲染了 src/ThumbnailDemo.tsx 以及一个直接使用Thumbnail的实例Thumbnail component{CarSlideshow} frameToDisplay{480} compositionWidth{500} compositionHeight{200} durationInFrames{5000} fps{30} inputProps{{title: Hi there, bgColor: black, color: white}} style{{border: 4px solid red}} /Thumbnail与Player共享合成组件和inputProps契约但只渲染frameToDisplay指定的静态帧——适合作为视频封面、编辑器时间轴缩略图。同一页面还包含 src/FontPicker.tsx 提供的字体选择器用于验证不同字体在 Player 中的加载表现。实践要点小结结合 SKILL.md 的工作流与源码结构本地演练remotion/player的正确姿势可以归纳为在仓库根目录执行bun i bun run build或先用bun run makeplayer只构建 Player 包以节省时间cd packages/player-example bun run dev以终端打印的实际地址默认http://localhost:3000端口冲突时会顺延为准从首页路由索引进入/player主测试床用按钮面板逐项验证Playerprops 的热更新、PlayerRef命令式方法与 13 种事件需要验证特定边界行为时切换到/fullscreen、/video-ssr、/autoplay-unmuted-video等专项页面该包为内部示例README.md 明确标注 “internal package and has no documentation”其价值不在于对外文档而在于作为 Player API 变更时的可执行回归测试床——根脚本testnextjs还会通过next build保证它在 Next.js 16 生产构建下始终可用。【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考