- 人工智能
- AI Agent
- 代码智能体
- 开发工具
【免费下载链接】stagewise
The Open Source Agentic IDE. Create and orchestrate coding agents, show app previews and run git workflows. Use your favorite models across all providers.
导读
本文以 Stagewise 仓库内置的 Remotion 视频创作技能(SKILL.md)中的规则文档为核心,系统讲解在 Remotion 项目中如何通过@remotion/media的<Video>组件导入本地与远程视频,并完成裁剪(trim)、延迟(delay)、缩放定位(style)、音量(volume)、静音(muted)、变速(playbackRate)、循环(loop)与变调(toneFrequency)等全套控制。文章同时结合仓库中同目录的配套规则文档(assets、audio、trimming、sequencing、can-decode、get-video-dimensions、get-video-duration 等)与技能流程,给出可直接复制运行的代码示例与底层原理,帮助你无论作为 Agent 还是开发者,都能在 Stagewise 的"创建 Remotion 视频"工作流中精确地使用视频素材。
一、前置准备:把视频放进 Remotion 项目
在 Stagewise 的 Remotion 技能流程中,所有素材(图片、视频、音频、字体)都必须先复制进项目根目录的public/文件夹,再通过staticFile()引用(见 assets.md)。这条规则同样适用于视频:永远不要把视频文件散落在组件目录里,一律放入public/。
import { Video } from "@remotion/media"; import { staticFile } from "remotion"; export const MyComposition = () => { return <Video src={staticFile("video.mp4")} />; };- 若项目尚未安装
@remotion/media,先通过npx remotion add @remotion/media(或pnpm exec remotion add @remotion/media,依据项目包管理器选择)安装。 staticFile()会返回经过编码的 URL,在子目录部署(subdirectory deploys)下依然可用,是引用public/内文件的推荐方式。- 文件名中的特殊字符(
#、?、&)会被自动编码,无需手工处理。
远程 URL 同样可用
规则文档明确:远程 URL 可以直接作为src传入,不需要包staticFile():
<Video src="https://remotion.media/video.mp4" />加载行为说明
<Video>(以及<Img>、<Audio>)这类 Remotion 组件会等待资源完全加载完成后才进入渲染,因此无须在组件内自行做加载状态判断,这是 assets.md 明确给出的行为约定。
二、裁剪视频:trimBefore与trimAfter
规则文档给出的裁剪方式与音频规则(audio.md)一致:通过trimBefore+trimAfter指定要保留的片段,数值单位是帧(frames),需要结合useVideoConfig()拿到的fps换算成秒。
import { useVideoConfig } from "remotion"; export const MyComposition = () => { const { fps } = useVideoConfig(); return ( <Video src={staticFile("video.mp4")} trimBefore={2 * fps} // 剪掉前 2 秒 trimAfter={10 * fps} // 保留到第 10 秒 /> ); };要点:
- 裁剪后,视频仍然从合成(composition)的第 0 帧开始播放,只是实际播放的内容是被选中区间的那一段;这与音频规则中"Still starts at composition start. Only selected slice plays."的行为一致。
- 通过
fps而不是写死帧数,可以保证不同帧率项目下的裁剪时间语义一致。
三、延迟出现:用<Sequence>包装
如果希望视频不是从第 0 帧就开始,而是在若干秒后出现,规则文档给出的做法是把它包进<Sequence>并设置from:
import { Sequence, staticFile, useVideoConfig } from "remotion"; import { Video } from "@remotion/media"; export const MyComposition = () => { const { fps } = useVideoConfig(); return ( <Sequence from={1 * fps}> <Video src={staticFile("video.mp4")} /> </Sequence> ); };上面的例子中,from={1 * fps}表示视频在合成开始 1 秒后才出现。
配套的 sequencing.md 补充了更多时序控制细节,可作为深化参考:
<Sequence>默认会把子元素包裹进一个absolute fill(绝对定位填充)容器,若不需要这种包裹行为,可传layout="none"。- 建议给
<Sequence>加premountFor,让组件在真正进入播放时间之前提前加载,避免出现卡顿:
<Sequence from={1 * fps} durationInFrames={2 * fps} premountFor={1 * fps}> <Title /> </Sequence>- 在
<Sequence>内部使用useCurrentFrame()时,返回的是从 0 开始的局部帧号,而不是全局帧号,这一点在做内部动画时要注意。
四、缩放与定位:style
视频在合成中的尺寸和位置通过标准的style对象控制,规则文档给出的示例同时演示了固定宽高、绝对定位与裁剪适配三种能力:
<Video src={staticFile("video.mp4")} style={{ width: 500, height: 300, position: "absolute", top: 100, left: 50, objectFit: "cover", }} />position: "absolute"+top/left用于把视频精确放到合成画布的任意位置。objectFit: "cover"让视频按"封面"模式填满指定宽高、必要时裁掉溢出部分,常用于背景视频或需要统一比例的卡片场景。- 由于 Remotion 本身就是 React,
style的语义与浏览器 CSS 一致,任何响应式布局思路(如基于useVideoConfig()计算百分比)都可以直接复用。
五、音量控制:静态volume与动态回调
规则文档给出了两条音量控制路径。
5.1 静态音量
volume取值范围为0 到 1,直接传入常量即可:
<Video src={staticFile("video.mp4")} volume={0.5} />5.2 动态音量(回调)
把volume写成接收当前帧f的回调函数,再配合interpolate做随时间变化的音量曲线:
import { interpolate, useVideoConfig } from "remotion"; export const MyComposition = () => { const { fps } = useVideoConfig(); return ( <Video src={staticFile("video.mp4")} volume={(f) => interpolate(f, [0, 1 * fps], [0, 1], { extrapolateRight: "clamp" }) } /> ); };上面的写法实现"前 1 秒从无声渐入到全音量"。extrapolateRight: "clamp"保证超过输入区间后音量维持在末端值,不再继续增长。需要注意:在<Audio>组件中,回调的f是从音频开始播放时算起(从 0 开始),而不是合成全局帧;视频组件的回调语义与其一致,设计音量曲线时应以此为基准。
六、静音:muted
传入muted即可静音整个视频的音轨,用法与音量为静态常量时相同:
<Video src={staticFile("video.mp4")} muted />动态静音(例如"第 2~4 秒间静音")在 audio.md 中给出了模式:muted可以接受布尔表达式,如muted={frame >= 2 * fps && frame <= 4 * fps},视频组件同样适用这一模式。
七、变速播放:playbackRate
playbackRate控制播放速度,默认值为 1。大于 1 加速,小于 1 减速(但仍为正向播放):
<Video src={staticFile("video.mp4")} playbackRate={2} /> <Video src={staticFile("video.mp4")} playbackRate={0.5} />⚠️ 规则文档明确声明:反向播放(reverse playback)不支持。请勿尝试使用负的playbackRate,Remotion 的媒体组件不支持逆向解码播放。
八、循环播放:loop与loopVolumeCurveBehavior
loop让视频无限循环:
<Video src={staticFile("video.mp4")} loop />当loop与动态volume回调组合使用时,loopVolumeCurveBehavior决定循环时回调收到的帧号如何计算:
"repeat":每次循环,帧号重置(回到 0 重新计)。适合音量曲线希望"每圈重新来一遍"的场景。"extend":帧号持续增长,不随循环重置。适合希望音量曲线在整段播放中一次性走完的场景。
官方示例("extend"模式,前 300 帧音量从 1 渐降到 0,之后保持静音般的低音量):
<Video src={staticFile("video.mp4")} loop loopVolumeCurveBehavior="extend" volume={(f) => interpolate(f, [0, 300], [1, 0])} />结合 audio.md 可知,"repeat"是默认值,与音频组件的语义完全一致。
九、变调不改速:toneFrequency
toneFrequency用于改变音调(pitch),取值范围为0.01 到 2,它只改变音高、不改变播放速度:
<Video src={staticFile("video.mp4")} toneFrequency={1.5} /> {/* 音调升高 */} <Video src={staticFile("video.mp4")} toneFrequency={0.8} /> {/* 音调降低 */}两个需要特别注意的限制(规则文档明确说明,且与 audio.md 一致):
- 变调只在服务端渲染(server render)时生效;
- Studio 预览中不生效;
<Player />中不生效。
因此,如果依赖toneFrequency变调,务必用服务端渲染产出的成片来验收效果,不要用 Studio 或 Player 预览判断。
十、纵深实践:解码校验、尺寸与时长探测
规则文档只解决"把视频放进画面",而"这个视频能否被浏览器解码、分辨率是多少、时长多长"这类问题,仓库配套的规则文件给出了 Mediabunny 方案,可在渲染前做防御性校验。
10.1 渲染前检查可解码性(can-decode.md)
先安装 Mediabunny:
npx remotion add mediabunny然后可复制以下canDecode工具函数(同时检查主视频轨与主音频轨):
import { Input, ALL_FORMATS, UrlSource } from "mediabunny"; export const canDecode = async (src: string) => { const input = new Input({ formats: ALL_FORMATS, source: new UrlSource(src, { getRetryDelay: () => null }), }); try { await input.getFormat(); } catch { return false; } const videoTrack = await input.getPrimaryVideoTrack(); if (videoTrack && !(await videoTrack.canDecode())) { return false; } const audioTrack = await input.getPrimaryAudioTrack(); if (audioTrack && !(await audioTrack.canDecode())) { return false; } return true; };使用方式:
const src = "https://remotion.media/video.mp4"; const isDecodable = await canDecode(src); if (isDecodable) { console.log("Video can be decoded"); } else { console.log("Video cannot be decoded by this browser"); }若视频来自上传或拖拽(Blob),把UrlSource换成BlobSource即可,校验逻辑不变。
10.2 获取分辨率(get-video-dimensions.md)
import { Input, ALL_FORMATS, UrlSource } from "mediabunny"; export const getVideoDimensions = async (src: string) => { const input = new Input({ formats: ALL_FORMATS, source: new UrlSource(src, { getRetryDelay: () => null }), }); const videoTrack = await input.getPrimaryVideoTrack(); if (!videoTrack) { throw new Error("No video track found"); } return { width: videoTrack.displayWidth, height: videoTrack.displayHeight, }; };对public/内的文件,用staticFile()包装路径传入即可,例如getVideoDimensions(staticFile("video.mp4"))。该 API 在浏览器、Node.js、Bun 中均可用。
10.3 获取时长(get-video-duration.md)
import { Input, ALL_FORMATS, UrlSource } from "mediabunny"; export const getVideoDuration = async (src: string) => { const input = new Input({ formats: ALL_FORMATS, source: new UrlSource(src, { getRetryDelay: () => null }), }); const durationInSeconds = await input.computeDuration(); return durationInSeconds; };在 Node.js / Bun 环境使用本地文件时,将UrlSource换成FileSource(file);浏览器拖拽上传场景同样使用FileSource。知道精确时长后,你就能基于getVideoDuration(staticFile("video.mp4"))的结果,为<Video>设置准确的trimAfter,或为整段合成(composition)计算durationInFrames。
十一、组合示例:一段"延迟出现、裁剪、渐入、循环"的视频
将上述规则组合成真实可用的成分(composition)示例:
import { Sequence, staticFile, interpolate, useVideoConfig } from "remotion"; import { Video } from "@remotion/media"; export const MyComposition = () => { const { fps } = useVideoConfig(); return ( <Sequence from={1 * fps}> <Video src={staticFile("video.mp4")} trimBefore={2 * fps} trimAfter={10 * fps} style={{ width: 1280, height: 720, position: "absolute", top: 100, left: 50, objectFit: "cover", }} volume={(f) => interpolate(f, [0, 1 * fps], [0, 1], { extrapolateRight: "clamp" })} loop loopVolumeCurveBehavior="extend" /> </Sequence> ); };行为解读:
- 第 1 秒后视频才出现(
Sequence from={1 * fps}); - 只播放源视频第 2~10 秒的片段(
trimBefore/trimAfter); - 固定为 1280×720 并绝对定位,
cover裁剪填充; - 音量在出现后的 1 秒内从 0 渐入到 1,并因
loop+"extend"而在循环播放中保持同一条音量曲线持续延伸。
十二、在 Stagewise 的 Remotion 视频工作流中的位置
这段视频规则并非孤立存在,而是 Stagewise 内置 Remotion 技能(SKILL.md)的"规则库"之一。从技能流程看:
- 技能要求把所有素材先放进
public/,再统一通过staticFile()引用,与 assets.md 完全对应; - 技能默认30 fps("Default to 30fps"),因此本文所有
X * fps的写法在默认项目里等价于"X 秒"; - 视频相关需求(导入、裁剪、音量、速度、循环、变调)时,技能会引导读取 videos.md,本文即该文件的完整展开;
- 涉及静音片段裁剪、字幕等场景时,技能还会交叉引用 ffmpeg.md、silence-detection.md、subtitles.md 等规则文件,形成完整的视频制作链路。
十三、快速自查清单
@remotion/media已安装(npx remotion add @remotion/media)- 视频文件已复制进项目根目录
public/,并用staticFile()引用;远程 URL 直接传入 - 裁剪使用帧单位:
trimBefore/trimAfter均乘以fps - 延迟出现使用
<Sequence from={N * fps}>,并建议加premountFor - 音量取值范围 0~1,动态曲线用回调 +
interpolate muted可传布尔表达式实现动态静音playbackRate仅支持正向(默认 1,不支持反向)- 循环时按需选择
loopVolumeCurveBehavior:"repeat"(默认)或"extend" toneFrequency(0.01~2)只在服务端渲染生效,Studio 与<Player />无效- 渲染前用 Mediabunny 的
canDecode/getVideoDimensions/getVideoDuration校验素材
遵循以上规则,你就能在 Stagewise 的 Remotion 视频创作工作流中,像使用专业剪辑软件一样精确控制每一段视频素材的引入、裁剪、时序、布局、音量和播放行为。
- 人工智能
- AI Agent
- 代码智能体
- 开发工具
【免费下载链接】stagewise
The Open Source Agentic IDE. Create and orchestrate coding agents, show app previews and run git workflows. Use your favorite models across all providers.
相关推荐
Remotion 视频嵌入与处理:在 React 合成中使用 @remotion/media 实现裁剪、变速、循环与变调
Remotion 视频嵌入与处理:在 React 合成中使用 @remotion/media 实现裁剪、变速、循环与变调 导读 本文围绕 Remotion 官方
音视频AI 应用前端Stagewise 中基于 Remotion 的 FFmpeg 视频处理指南:免安装调用与无损裁剪
Stagewise 中基于 Remotion 的 FFmpeg 视频处理指南:免安装调用与无损裁剪 在 Stagewise 开源仓库中, apps/browse
人工智能AI Agent代码智能体开发工具使用 Remotion 定义视频合成(Composition):Stagewise 中可渲染视频的组件、尺寸、帧率与动态元数据完整指南
使用 Remotion 定义视频合成(Composition):Stagewise 中可渲染视频的组件、尺寸、帧率与动态元数据完整指南 导读 本文围绕 Stag
人工智能AI Agent代码智能体开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考