关于 create-motion-graphics
create-motion-graphics 是面向 ChatCut Web 编辑器的技能,用于通过 JSX 创建或修改 Motion Graphic 素材。它要求依据项目样式、画面与内容选择参考,并检查图形在实际镜头中的效果。
主要功能
- 01浏览并选择视觉样式与图形参考
- 02根据项目样式编写或修改 JSX 图形
- 03将可变文字、颜色和数值设为可编辑属性
- 04依据镜头与语音确定构图和时长
- 05修改后检查项目状态与画面效果
适用场景
- 01为视频制作与项目风格一致的动态图形
- 02调整现有 Motion Graphic 的文本或视觉属性
- 03根据目标镜头安排图形的位置与动画时长
MCP 相关
该技能要求使用 chatcut MCP 服务处理 ChatCut Web 项目,通过 create_motion_graphic_from_code 创建图形,并用 edit_asset 修改现有图形。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ chatcut-inc/ agent-plugin --skill create-motion-graphics安装后在 Claude Code 中输入/create-motion-graphics确认已加载。
附带文件references/font-matching.mdreferences/overlay-composition.md
详细介绍
创建动态图形
插件宿主和项目
使用 chatcut MCP 服务,以及用户编辑器 URL 中的项目 ID 或插件返回的项目结果。此插件适用于 Web 编辑器,包括本地开发 URL。对于 Web 项目,不要打开 ChatCut Desktop,也不要使用 chatcut_desktop。如果 chatcut 工具不可用,请报告连接失败;不要改为将任务提交给编辑器的原生 Agent。
设计前查找动态图形参考
浏览并确认视觉方向
用于制作时,沿用已获认可的项目风格,或用户提供的品牌/参考资料。如果尚不清楚完整规格,请使用 manage_design_style get。日常的文本/位置调整无需重新选择风格或重新扫描目录。
需要新的视觉方向或用户要求浏览其他选项时,先使用 browse_library,并设置 references: {view: "style-overview"}。读取所有编号的联系表,并根据 nextOffset 继续浏览,直到 complete。这些联系表包含已发布且启用了 Agent 的风格示例,其中包括关联的现有 Design Styles。list_presets 只是旧版目录的子集,不能替代此视觉概览。页面加载失败时请重试;如果概览不完整,请明确报告,不要默默跳过。
对于以语音为主的视频,请先了解口播内容,并查看有代表性的视频帧,再筛选风格。重复使用上下文中已有的转录文本和视频帧证据。结合风格预览,考虑主题、表达语气、屏幕上的语言,以及素材的色彩、主体构图和背景。
如果视觉方向尚未达成一致,请为当前内容和素材筛选最多 6 种不同的合适风格,并读取其 hero 部分。加载宿主的 widget-forms 技能,并配上简短名称展示实际的 heroPreview.url 图片。工具返回的图片是供 Agent 参考的证据,不是面向用户的选择器;仅用文字展示选项无法体现视觉差异。将每个选项与其参考 ID 对应起来;使用表单中的 Other 分支收集偏好或提供另一批选项,不要重复展示已有选项,也不要另设 Show more 选项。
在应用新风格并制作动态图形前,等待用户选择,除非用户已选定方向或明确授权你代为选择风格。选择 Other 不代表用户已认可风格。
应用所选风格
阅读所选代表的 summary、hero 和 members。使用 manage_design_style 执行其
designStyleAction:
apply_preset:直接使用返回的presetId;不要仅为保存参考元数据而克隆或更新预设。apply:对已有的已保存用户风格,复用返回的designStyleId。create:只有独立参考才需要创建新的用户自有风格。根据所选参考定义并保存其调色板、字体和可复用的视觉规则。 复用参考中记录的调色板;如果没有记录,则从其代表图像中提取协调的调色板。保存designSpec.referenceSources: [{id: "<reference ID>"}]和单独的heroPreview.url,并将其同时保存到thumbnailUrl和designSpec.images: [{role: "style reference", url: "<heroPreview.url>"}]。 使用applyToProject: true;修补数组时保留已有图像。
应用后,调用 get 获取最新的完整规格和来源 ID;不要沿用先前风格缓存的规则。对于新风格,确认其调色板、
字体、来源、封面和参考图像均已保存。仅有来源 ID 并不会保存图像。
参考图像是视觉证据,不是要嵌入的素材/背景或要照搬的示例文案。
根据屏幕上实际显示的文本(包括双语文本和拉丁数字),使用 fontRecommendations["zh-Hans"] / .en。复用已认可的字体方案;
未填写的语言组表示尚未解决。匹配参考的字体特征及标题/正文层级,并检查字形覆盖范围和运行时可用性。
在 designSpec.fonts 中保存所选字体系列/角色,并在 styleGuide 中保存语言、字重、斜体和必需的字轴。跨风格的表单示例不能替代此方案。仅在需要整理缺失字体或明确调整排版时,才阅读 字体匹配;中文匹配应从生成的中文效果图入手,而不是英文字符字形。
将实例匹配到所需的 MG 形式
根据口播内容和目标画面,判断哪些 MG 形式合适;
再参考预览图优化选择。在整个视频中保持已确认的视觉语言,
并为每种所需形式找到合适的实例。
除非用户要求对比,否则自行选择实例。不同形式可以使用不同实例;
重复出现的组件可以复用已检查的实例。
如果返回 nextReferenceSearch,请遵循其中的指引:
- 对于相关成员,可浏览
kind: "instance", styleId: "<representative UUID>"或读取相关成员 ID。 - 如果某种所需形式没有合适的成员,请按内容/形式在整个实例库中搜索,使用
query或facets.form,省略styleId、facets.style和风格名称词,即使其他形式已有相同风格的匹配项也不例外。 - 先对比封面拼图,再用
parts: ["summary", "hero"]读取选定的 ID。动画还要添加motion,实现参考还要添加code。如果代码支持的参考项返回templateInspection,请使用其中的只读调用读取已保存的属性架构/默认值;JSX 可以读取属性,但不一定声明其值。legacyTemplateRefs是模板 ID:manage_template get会读取元数据,list_assets会读取 MG 属性。两者都不会应用或复制模板。inspect_asset用于当前项目的媒体/MG,而非目录源 ID。
根据项目固定的字体、调色板、材质和实际镜头,调整实例的构图、层级、间距和显示结构。如果更广范围的形式搜索仍找不到合适项,请扩展风格参考板,并说明此限制。
批量读取相关的详细信息;找到一个实例并不意味着已覆盖无关形式。
对于拆分响应,请根据 pendingIds 继续处理;known 可能只包含已返回且仍在上下文中的版本和部分内容。每张动态分镜表都是一个在真实时间点呈现的设计;拼图不代表单一布局,静态图也无法证明动画效果。
对于新建或大幅重新设计的真人出镜叠加层,请阅读
叠加层构图。仅导入 materials 中会出现在成片里的生产文件;使用其项目资源 ID。查看与目标素材合成后的 MG。
编写内容时使用参考资料
如果要借用某个选定实例的实现,请读取其 code;或者使用 manage_template list_assets 读取关联模板的属性。在下面的代码工作流中将其作为参考,同时保留项目风格。
也要检查选定图像:仅有 URL、ID 或搜索结果并不算已查看参考。外观需有 STYLE 证据,结构需有跨风格的 FORM 证据。如果选定的参考无法使用,请重试,或说明缺少相应证据,不要声称已检查。
当 ChatCut 插件任务要求将 Motion Graphic 素材以内联 JSX 形式编写或修补时,请使用此技能。内置的 ChatCut Agent 有自己的 motion-graphic-gen 工作流;处理此插件任务时不要切换到该工作流。
Codex 插件的 Motion Graphics 需直接编写。新建 JSX 素材请使用 create_motion_graphic_from_code,编辑现有 MG JSX 请使用 edit_asset。此工具界面不提供 submit_motion_graphic;不要将请求改写成 Gemini 提示词或生成简报。如果缺少直接编写工具,请停止并报告 ChatCut 插件工具不可用。
通过 chatcut MCP 工具以内联方式传入 Motion Graphic 源码。工具支持直接传入内联 JSX 时,不要将代码暂存在 ChatCut 仓库、ai-working/、/tmp、本地 HTTP 服务、生成的代码文件或猜测的应用路径中。
核心原则
- 如果尚不清楚画布尺寸、fps、现有视觉风格、位置或时间线冲突,请先检查项目状态。
- 编写 JSX 前,先在 编码前 确认所需输入。
- 通过可用的内联代码资源工作流创建或更新动态图形资源;具体负载格式请以当前工具架构为准。
- 如果编辑需要在时间线上放置资源,请通过时间线编辑工作流放置或移动资源。
- 结构或视觉内容发生变化后,重新读取项目状态并检查可见画面。
编码前
编写 JSX 前,只需确认本次编辑所需的信息:
- 位置:开始时间、时长、目标图层(如果已知),以及图形必须与之协调的目标帧。
- 编辑中的作用:动态图形在视频中承担什么功能。
- 内容:必须显示的确切文本、数字、媒体或视觉信息。
- 时机:内部动画是否应与语音、音乐或视觉事件同步。
- 视觉来源:用户提供的风格、项目设计风格、品牌颜色/字体,或已接受的现有动态图形。
- 可编辑字段:哪些文本、颜色、数字、布尔值、图像或视频值应设为属性。
仅询问那些缺失且会实质性影响结果的关键信息。
视觉系统和位置
使用已确认的完整设计风格和上文检查过的参考。对于新的 自定义方向,批量制作前先确定一个完整方案;已接受的 方向和常规修正无需再次确认风格。
根据实际镜头和语音时长,选择每个构图的位置、尺寸和阅读时间。 保持字体、配色、材质和动效的一致,同时根据内容调整参考形式。只有在构图需要时,才使用固定的左/右锚点或卡片容器。
对于信息结构相同且有意重复使用的组件,复用资源并设置单项属性。 新结构需要自己的实例参考和构图。覆盖层边界应紧贴图形; 只有在设计明显跨越整个画面时,才使用时间线尺寸。
使资源时长和内部节拍与放置后的时间线时长匹配。如果时机发生重大变化, 应更新 MG,而不是截断尚未完成的动画。批量制作时,将构图完成后的静止帧并排检查,在报告完成前修正遮挡、 可读性问题和非预期重复。
可编辑属性
将用户可见且可能变化的值设为可编辑属性。
- 可见文本、主色、强调色和关键数值应设为属性。
- 如果用户可能会合理地修改字体选择,应将其设为
font属性。 - 图像和视频源必须设为
image/video属性。 - 代码中的键必须与属性架构中的键完全一致。
- 从
item.props读取值;对于用户之后可能会合理修改的可见内容,不要硬编码。 - 仅当组件的观看任务、信息结构和视觉形式都相同时,才使用项目级属性覆盖来复用组件。任一条件不同,都应创建另一个 MG 资源,并共享配色、字体和动效逻辑。
属性条目应声明稳定的键、面向用户的标签、类型和默认值。支持的属性类型包括 text、number、color、boolean、select、font、image 和 video。
字体
Motion Graphics 必须使用 ChatCut 渲染器支持的字体,确保预览与本地导出效果一致。不要依赖特定机器上的系统字体,例如 STKaiti、PingFang SC、Microsoft YaHei、Arial、Helvetica、Comic Sans MS、system-ui、-apple-system,或通用 CSS 字体族作为主要渲染字体;不同机器上的可用字体可能不同,并可能导致字体回退。
选择或替换字体时,请调用 search_fonts,并将返回的规范字体族名称原样用作 fontFamily 值和匹配的 font 属性 defaultValue。使用字体目录返回的 Google Fonts 或项目自定义字体。如果目录中没有用户指定的特定机器字体,请说明无法保证本地渲染效果一致,搜索风格相近的受支持替代字体,并使用该字体,除非用户明确接受字体回退。
素材与构图
一个参考实例可能描述由多个时间线项目组成的完整构图。这并不意味着它是一个独立完整的 MG 素材。请区分参考截图、制作素材和当前项目中的视频素材。
当设计将普通媒体与图形结合时,默认使用单独的项目:
- 可复用的纸张/纹理/背景:放在构图后方的图像或视频项目。
- 当前项目中的照片、产品图像或视频素材:使用其独立的媒体项目。Agent 负责选择/替换、裁剪、定位,并应用受支持的效果;不应要求用户手动组装图层。
- 字体、形状和动画装饰:使用透明 MG 项目。若媒体需要置于背景装饰与前景文字之间,请将背景装饰与前景文字拆分。
创作前,规划图层顺序、目标媒体矩形、开始时间/时长和入场时机。在 MG 简介/代码范围中说明哪些图层已存在于 MG 之外,避免再次生成参考图中的照片或纸张。将黑白/色彩/颗粒效果应用到指定的媒体项目上,避免意外影响前景文字。请在实际播放/导出环境中验证效果是否受支持;拆分图层本身并不能证明 Web/Desktop 效果一致。
- 从当前项目的
browse_assets中复用素材。仅将输出所需的制作文件导入 My Assets。加载asset-import,并使用其import_media会话/上传辅助工具。注册项目媒体不会将其发布到公共资源库。 - 使用
edit_item放置常规制作媒体,并使用返回的当前项目素材 ID。Agent 负责将示例人物、文案和数据替换为当前任务的内容。不要将参考图中的完整效果截图用作背景。 - 仅当视觉效果机制需要时,才将媒体嵌入 MG,例如图像填充文字,或可用时间线工具无法实现的紧密同步内部蒙版。对于此类例外情况,
image/video属性的默认值和覆盖值必须绑定到完整的当前项目素材 ID,不得使用 URL、本地路径或参考库 ID。通过item.props读取,处理空值,并让运行时解析来源。声明图像属性并不会导入文件。 - 在入场帧和稳定帧检查合成时间线,包括媒体是否存在、裁剪、效果、图层顺序和时序。独立的透明 MG 预览会有意省略单独放置的照片/背景;应在时间线上评估完整设计。对于有意嵌入的媒体,仅凭正确的缩略图无法证明播放正常;若媒体缺失,请检查导入情况、ID 绑定和字节就绪状态。
资源库中的 hero/motion 图像仅用于研究,无需仅为查看而导入项目。必须报告缺失的制作文件,或用合适的可用素材替代;切勿默默省略必需图层。
设计原则
根据已确认的风格和已检查的实例设计定格画面,然后再为其添加动画。利用参考内容的层级和视觉关系,让当前内容清晰易读;不要添加填充性的标签或默认卡片容器。
将明确的字体、材质和运动规则视为约束。硬切风格不应添加淡入淡出或弹簧效果;玻璃、颗粒、辉光和其他处理方式,只应在既定视觉语言需要时使用。既要保留参考内容的表现力,也要保留其克制之处。
字符、插图或复合形状都属于一个视觉实体。当多个部分需要在视觉上连接、附着或对齐时,应将这些部分放在同一个 <svg> 中渲染,并使用同一坐标空间和命名锚点。在不同容器中分别硬编码 left / top,会造成明显的间隙。
文本布局安全性
对于包含文本的 MG,应先将定格画面设计为真实布局,再添加动画。相关文本块应使用 flexbox 或 grid、gap、padding、maxWidth、lineHeight 和自然换行。除非文本是有意设计的装饰元素或字体艺术,否则不要用彼此独立的硬编码 top 值堆叠可读文本。
可编辑文本可能比默认内容更长。应为合理的较长文案预留空间,允许通过 whiteSpace: "normal" 和 overflowWrap: "break-word" 换行;如果内容无法妥善容纳,则应降低层级、字号或密度,或更改表现形式。
动画变换不会影响布局。如果文本在其他文本附近缩放、脉动、滑动或错开,应为动画幅度最大的状态留出视觉空间。图形图层、阴影、标记或装饰性字体可以有意重叠;普通可读文本则不得相互碰撞。
避免对动态文本使用强制 <br> 或手动换行,除非每一行都是有意固定的。优先使用受宽度约束的自动换行。
使用以下基础组件结构:
const Component = ({ item }) => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
const props = item.props || {};
const accentColor = props.accentColor;
const rootStyle = {
position: "absolute",
inset: 0,
backgroundColor: "transparent",
};
return <div style={rootStyle}>{/* content */}</div>;
};
动态图形代码规范
违反规范会导致运行时崩溃。必须严格遵守。
- 语法: 纯 JavaScript JSX。不使用 TypeScript。
- 导入: 不使用 import 语句。以下全局变量已预先注入:
React、spring、useCurrentFrame、useVideoConfig、interpolate、interpolateColors、Math、random、Easing、AbsoluteFill、Sequence、Series、Img、Video和Audio。 - 使用注入的全局变量: 可直接使用 Hooks 和组件;不要通过命名空间对象访问它们。
- 导出: 不使用
export default。定义const Component = ...。 - 时间控制: 组件内部不要使用
Sequence包装器。使用扁平的帧驱动逻辑。 - 逻辑: 不要在 JSX 属性中内联逻辑。在
return之前将值预先计算到变量中。 - 辅助函数: 不要使用未定义的函数。使用复数形式的
interpolateColors。在本地定义所有辅助函数。 - AbsoluteFill:
AbsoluteFill是组件,不是样式对象。绝不要展开它。可以将它用于内部图层,但绝不能将它用作根元素。 - 根元素: 根元素必须是
<div style={rootStyle}>。 - 素材:
<Img>和<Video>的来源必须读取图像/视频可编辑属性。绝不要硬编码 URL。如果没有提供素材,请使用形状、文字和 CSS 进行设计。 - Hooks: 使用
useCurrentFrame()获取帧,而不是useVideoConfig()。 - 局部盒子: 组件必须接受
({ item })属性。素材的width/height是 MG 围绕其可见局部构图的自然盒子,不是时间线画布;使用position:absolute; inset:0填满该盒子。时间线布局会设置最终屏幕尺寸和位置。 - 布局控制: 使用 flexbox 或 grid 布局文本块和结构化内容。如果设计依赖空间关系、复合形状、边框效果或绘制/动画标记,请使用 SVG 或绝对定位几何布局。除非需求要求文本单行显示,否则应允许文本自然换行。
- 可编辑属性: 组件必须从
item.props读取可编辑值。props.key后绝不要添加|| "Default"或?? false等回退值;已声明的运行时属性已有对应值。 - 属性架构: 声明匹配的可编辑属性。包含所有可见文本内容以及主色/强调色。
- 图像/视频属性: 在媒体属性中存储项目素材 ID,从
item.props读取运行时值,并且仅当该值为真值时才渲染<Img>/<Video>。 - 背景: 默认背景为透明。如果添加背景表面,请提供一个
transparentBackground布尔属性。 - 导出成本: 保持内联
<svg>标记在每一帧中不变:为外层<div>添加动画(transform、opacity),不要修改<svg>属性,因为导出时只有标记发生变化才会重新绘制 SVG。优先使用 HTML/CSS 形状,而不是承载照片的 SVG;优先使用boxShadow发光效果,而不是大型模糊图层;这两种方式在每帧导出时的成本都高出数倍。
渲染器 CSS 支持
布局安全:浏览器会在导出渲染器测量结果之前解析 flexbox、grid、gap、padding、margin、position、width、
height、inset、whiteSpace 和 overflowWrap。以下绘制时属性则不然。这些属性在导出时会丢失或发生变化,但在编辑器预览中仍会正确显示:
backdropFilter— 渲染器无法采样元素后方已绘制的内容。替代方案:使用半透明的 backgroundColor 加边框和柔和的 boxShadow 来构造磨砂玻璃效果,而不是实时模糊视频画面。mixBlendMode / isolation— 图层只会以普通混合模式绘制。替代方案:直接选择最终颜色,或叠加半透明填充。zIndex— 渲染器按 DOM 顺序绘制元素。替代方案:调整元素的顺序,让应位于上层的元素最后绘制。visibility: 'hidden'— 元素仍可能被绘制到导出内容中。替代方案:使用 display: 'none' 或 opacity: 0 隐藏元素。backgroundBlendMode— 背景图层只会以普通混合模式绘制。替代方案:直接选择最终颜色,或在颜色上叠加半透明渐变。perspectiveOrigin— 渲染器不会读取此属性(也不会读取它所调整的 perspective 属性)。替代方案:在自身 transform 中使用 perspective() 的元素上,通过 transformOrigin 移动消失点。perspective (the style property)— 渲染器不会读取此属性,因此以 3D 方式旋转的子元素会呈现扁平效果,仿佛被压扁了。替代方案:将 perspective() 放在旋转元素自身的 transform 开头,例如 transform: 'perspective(800px) rotateY(30deg)'。transformStyle: 'preserve-3d'— 嵌套的 3D 场景不会被合成,因此经父元素旋转的子元素会消失。替代方案:将每个面作为同级元素,并为其设置完整的 transform(依次包含 perspective()、共享的相机旋转、各自的旋转和 translateZ),添加 backfaceVisibility: 'hidden',并按从后到前的顺序列出各个面。gradient interpolation hints and color spaces— 导出渲染器不会保留颜色提示(red, 30%, blue)和显式插值空间(in oklch)。替代方案:使用普通渐变语法显式指定中间颜色停靠点。boxShadow with inset— 内阴影会被跳过,只绘制外阴影。替代方案:使用渐变背景或半透明边框为内部添加阴影。url() in background / backgroundImage— 不会绘制图像背景,只保留纯色背景 color。替代方案:在内容后方放置一个。
vertical writingMode— 垂直文本完全不会绘制。替代方案:在 flex 列中为每个字符堆叠一个元素,或将水平文本行旋转 90 度。filter: url(...) on an HTML element— SVG 滤镜引用会被忽略,因此元素绘制时不会应用滤镜。替代方案:使用 CSS filter 函数(blur()、drop-shadow()、brightness() 等),或在 内部的图形上应用 SVG 滤镜。clipPath: url(...) on an HTML element— clip-path 引用会被忽略,因此元素绘制时不会被裁剪。替代方案:使用基本形状:circle()、ellipse()、inset()、polygon() 或 path('…')。URL masks with unsupported sources or layout— 蒙版加载器要求使用栅格图像(SVG 蒙版无法使用),并会拒绝不支持的尺寸、重复、位置、原点、裁剪或非 alpha 模式。替代方案:使用 PNG/WebP 栅格蒙版,并设置 maskSize: '100% 100%'、maskRepeat: 'no-repeat'、maskPosition: '0% 0%'、maskOrigin: 'border-box'、maskClip: 'border-box',以及 maskMode: 'alpha' 或 'match-source';也可以使用渐变蒙版。currentColor inside <svg>— 每个 都会被栅格化为图像,并按其标记和继承的颜色进行缓存,因此每帧变化的颜色都会导致每帧重新解码每个 SVG(一个由几百个元素组成的网格就能让导出帧率从 10 fps 降至停滞)。替代方案:为 SVG 填充和描边指定显式颜色或属性值;绘制包含大量小图形的网格时,使用 CSS(带 border-radius 的圆点、带边框的三角形),而不是每个单元格都使用一个 。SVG <animate> / <animateTransform> / <animateMotion> / <set>— SMIL 动画使用浏览器时钟运行,而不是合成帧:预览不会跟随拖动播放头,导出时每个 都会重新栅格化,因此动画始终停留在第一帧(描边绘制动画或增长的柱条都不会出现)。替代方案:使用 interpolate() 或 spring(),通过 useCurrentFrame() 驱动属性,例如 strokeDashoffset={interpolate(frame, [0, 20], [length, 0], { extrapolateRight: 'clamp' })}。 适合安全导出的内容:filter: blur()发光效果和boxShadow发光效果会超出元素范围;<svg>根元素可以绝对定位、使用百分比尺寸,并包含<image>;逗号分隔和重复平铺的渐变背景(backgroundSize+backgroundRepeat)会绘制每一层。优先使用boxShadow发光效果,而不是大面积模糊图层:导出成本更低。每个屏幕上的<svg>在其标记或继承的颜色发生变化时,都会产生一次图像解码,因此每帧只保留几十个 SVG,并用普通 div 构建重复的点、条或三角形网格。
Canvas:<canvas>(2D 和 WebGL)会原样导出绘制内容,因此适用于粒子场、程序化绘图、噪声,以及其他需要数百个元素才能实现的效果。为其设置与 CSS 尺寸相同的 width / height 属性,并在 React.useEffect(() => { ... }, [frame, props]) 中绘制,或使用回调 ref:每次都根据 frame 和 props 同步清除并重绘整个 canvas,因为导出会跳转到任意时间点,分块导出也会以乱序渲染帧。切勿使用计时器、requestAnimationFrame 或异步操作,也不要累积上一帧的状态。使用 new OffscreenCanvas(w, h) 在 React.useMemo 中一次性构建开销较大的静态图层(document 不可用),并在每帧使用 drawImage 绘制这些图层。Canvas 文本只能使用已加载的字体,因此也要在 DOM 元素上设置相同的 fontFamily。无法将图像绘制到 canvas 中;应改用 <Img> 图层,将其放在 canvas 上方或下方。让每帧绘制保持轻量:它会直接增加导出耗时。
**动画工具包。**这些辅助工具已作为全局变量预先注入(Remotion 包以其导出名称提供,另有 Icon、d3、culori 和 useGsapTimeline);切勿导入它们。
- 自行绘制的线条和变形的形状(
@remotion/paths):getLength(d)、getPointAtLength(d, length)和getTangentAtLength(d, length)可沿路径移动元素;interpolatePath(progress, fromD, toD)可将一种形状变形为另一种形状;evolvePath、parsePath、scalePath、translatePath、reversePath、cutPath、getSubpaths、normalizePath、warpPath和getBoundingBox可编辑路径数据。SVG 标记必须在帧间保持不变,因此请在<canvas>上为描边和变形添加动画:ctx.setLineDash([len, len]); ctx.lineDashOffset = len * (1 - progress); ctx.stroke(new Path2D(d))可绘制出逐渐显现的线条,ctx.fill(new Path2D(interpolatePath(progress, a, b)))可实现变形。 - 形状(
@remotion/shapes):makeStar、makePie、makeHeart、makeArrow、makeCallout、makeSpark、makeCircle、makeEllipse、makeRect、makeTriangle和makePolygon会返回{ path, width, height };组件<Star>、<Pie>、<Heart>、<Arrow>、<Callout>、<Spark>、<Circle>、<Ellipse>、<Rect>、<Triangle>和<Polygon>会将它们绘制为静态 SVG。对于每帧都会变化的形状(如逐渐填满的饼图),请改为在画布上填充其path。 - 有机运动(
@remotion/noise):noise2D(seed, x, y)、noise3D和noise4D会返回 [-1, 1] 范围内的确定性值;将frame / fps作为一个轴输入,即可实现漂移、摆动和浮动粒子,而不必使用Math.random。 - 文本布局(
@remotion/layout-utils):measureText({ text, fontFamily, fontSize, fontWeight })会返回{ width, height };fitText({ text, withinWidth, fontFamily, fontWeight })会返回填满指定宽度的fontSize;fitTextOnNLines和fillTextBox可自动换行。可将它们用于动态文字(根据测量宽度逐词放置)、随文字增长的下划线和高亮效果,以及恰好填满一行的标题。测量时使用与渲染时相同的 fontFamily 和字重。createRoundedTextBox(@remotion/rounded-text-box)会返回{ d, boundingBox },这是多行文本背后的高亮形状。 - 样式和变换(
@remotion/animation-utils):interpolateStyles(value, inputRange, [styleA, styleB])可对整个样式对象(颜色、不透明度、尺寸)进行插值;makeTransform([Transform.translate(x, y), Transform.rotate(deg), Transform.scale(s)])可根据Transform上的构造器(translate、rotate、scale、skew 及其 X/Y/Z 变体、perspective、matrix)生成变换字符串。 - 动态残影(
@remotion/motion-blur):<Trail layers={6} lagInFrames={0.6} trailOpacity={0.9}>…</Trail>会在快速移动的物体后留下残影;其子元素必须根据useCurrentFrame()播放动画。不支持摄像机动态模糊:导出时无法混合采样帧。 - 图标:
<Icon name="rocket" size={56} color="#ffca28" strokeWidth={2} />可根据 kebab-case 名称绘制任意 Lucide 图标("arrow-right"、"chart-line"、"shield-check"、"coffee"、"users"、"globe"、"lightbulb"、"brain" 等)。务必传入明确的color;请为包装元素(缩放、不透明度、位置)添加动画,而不要为图标自身的 props 添加动画。未知名称会被拒绝,并提示最接近的有效名称。 - 图表(
d3.*):比例尺(d3.scaleLinear、d3.scaleBand、d3.scaleTime、d3.scaleOrdinal等)、形状(d3.line、d3.area、d3.arc、d3.pie、d3.stack、d3.curveMonotoneX等曲线)、数组(d3.max、d3.extent、d3.range、d3.bin等)和布局(d3.hierarchy搭配d3.treemap、d3.pack、d3.partition)。d3 只负责计算数值和路径字符串:将条形和图块绘制为随frame延展的定位 div,并使用new Path2D(d)在<canvas>上描边或填充生成的路径(逐渐扩大的圆环可通过arcGen({ ...slice, endAngle: slice.startAngle + (slice.endAngle - slice.startAngle) * progress })实现)。绝不要使用 d3-selection、transitions 或 timers;它们不可用。 - 颜色(
culori.*):culori.interpolate([a, b], 'oklch')会返回一个接受 0–1 数值的函数,其结果可通过culori.formatHex转换;使用 OKLCH 混色时,颜色能保持鲜艳,而 RGB 混色会经过灰色。culori.wcagContrast(a, b)可为背景选择易读的文字颜色;culori.samples(n)会为调色板生成间距均匀的色阶。 - GSAP 时间线(
useGsapTimeline):const scope = useGsapTimeline(({ timeline, selector }) => { timeline.from(selector('.word'), { y: 40, opacity: 0, duration: 0.5, ease: 'back.out(1.7)', stagger: 0.08 }, 0); }),然后使用<div ref={scope}>…</div>。时间线会暂停,并定位到当前帧,因此结果具有确定性;请以秒为单位设置时长,通过selector按 className 指定目标元素,并且绝不要调用 play()、seek()、回调函数或随机值(这些操作会抛出异常)。DrawSVG({ drawSVG: '0%' })、MorphSVG({ morphSVG: targetPathElement })和 MotionPath({ motionPath: { path, align, alignOrigin: [0.5, 0.5] } })插件均已注册。DrawSVG 和 MorphSVG 每帧都会重写 SVG 标记,这是唯一允许 SVG 在帧间变化的例外:每个图形最多在两个路径上使用它们,其余内容请绘制在画布上。由 GSAP 管理它所动画的属性:不要同时在该元素的 React style 中设置 transform 或 opacity。 <FitText maxFontSize={56} minFontSize={32} lines={1} style={{ width: 360 }}>{props.value}</FitText>会缩小文本,直到它适合文本框,且最多占用lines行;文本框必须具有有界宽度。- 3D:导出时只会将
perspective()应用到元素自身的 transform,因此请在旋转元素本身上设置transform: 'perspective(800px) rotateY(30deg)'。对于实体(立方体、有正反两面的翻转卡片),将每个面设为兄弟元素,并为其设置完整变换链perspective(800px) rotateX(a) rotateY(b) <face rotation> translateZ(d),设置backfaceVisibility: 'hidden',并按从后到前的顺序列出各个面。 - 直接调用注入的全局变量,例如
useCurrentFrame、spring和interpolate:从React解构它们会得到 undefined。 共享 Web 验证。create_motion_graphic_from_code以及通过edit_asset进行的源代码/架构变更使用相同的 Web 验证器。授予metadata.renderContract: "web-renderer-v1"之前,必须修复语法/API 错误和已知的渲染器不兼容问题。不确定的静态检查结果属于非阻塞警告,而非渲染失败:最多进行一次尽力修复,然后接受已写入标记的结果,不要反复改写。资产编辑可以应用报告的自动修复。生成过程会在有限的尝试次数内重试已知的不兼容问题;如果问题仍然存在,生成结果可以不带标记。edit_item的放置和实例变更不会重新验证源代码,也不会写入标记。validateOnly不会写入内容。inspect_asset和preview_timeline保持只读,也不会授予标记。桌面端使用单独的原生策略。
放置与审核
不要仅凭时间信息编写 JSX。先检查目标帧:时间信息告诉你何时显示;画面则告诉你形式、位置和背景。对于一批叠加元素,先制作一张目标帧截图/联系表,并在选择最终锚点、尺寸和时长之前,确定每个 MG 的定格帧、语音区间、阅读时间和放置关系。
先设计定格帧:选择 MG 最易读的时刻,在那里放置最终布局,然后再动画过渡到该构图。
编写 JSX 之前,先做出四项相互关联的编辑决策。这些决策有助于准备动态图形素材,并为之后的时间线放置做准备。
| 决策 | 问题 | 输出 |
|---|---|---|
| 内容 | 什么想法值得用视觉图层呈现? | MG 所表达的信息或视觉事实。 |
| 时间 | 何时出现和离开? | 语音区间、阅读时间、时长,以及任何内部动态节拍。 |
| 形式与位置 | 这是什么类型的 MG?它应放在合成画面的什么位置? | MG 的形式/尺寸,然后在素材创建后使用 edit_item 设置位置。 |
| 背景 | 这是叠加在视频素材上的元素,还是独立的片段? | 透明或不透明背景。 |
放置原则:
- 根据检查过的画面,将视频素材与 MG 一起构图:考虑主体、摄像机取景、视觉权重、字幕/字幕文本(如有)以及 MG 的作用。
- 将 MG 放在最能提升该时刻画面可读性的位置。
- 确保必要信息在视频尺寸下无需缩放即可读;如果 MG 显得脱离画面,应更改形式、时间、尺寸,或跳过。
- 仅在存在或计划添加字幕时考虑字幕。
- 将全屏 MG 视为有意设计的节拍,而不是解决叠加元素位置不佳的权宜之计。
除非计划使用全屏节拍,否则默认采用透明叠加层。透明叠加层仍应使用自然尺寸的素材框;不要仅为了放置而使用与时间线同尺寸的透明素材。
放置并审核:
- 使用
edit_item放置(添加/更新)。了解画面后,优先指定明确的矩形:一个水平锚点、一个垂直锚点、宽度和高度。 - 用截图验证。在一次工具调用中传入多个帧——定格状态会与动画中途的瞬态帧一同显示。下结论前先比较这些帧:如果截断、元素缺失或“设计损坏”的现象只出现在批次中的部分帧,那是动画效果,并非真正的问题。如果无法确定,在调整之前围绕可疑帧重新截取更多画面。应根据定格帧进行判断。
- 检查完整画面:必要信息在视频尺寸下清晰可读,字幕(如有)仍然易读,MG 内容正确,文字清晰易辨,整体构图平衡且经过有意设计。
- 对于文字较多的 MG,检查文字显示最多时的定格帧。确认文字之间没有重叠、没有行被裁切、内容没有超出素材自然尺寸框,也没有被缩放或平移动画状态遮挡。
- 如果效果不佳,先调整位置和尺寸。如果调整位置/尺寸仍无法解决问题,就更改设计形式。扩展使用之前,先在目标帧上验证每种重复使用的组件形式。
素材与时间线流程
创建新素材
通过当前的 ChatCut 素材创建工具传入内联 JSX 和可编辑的属性元数据,创建新的动态图形(Motion Graphic)素材。请根据工具架构确定准确的字段名称和支持的时长格式。
根据编辑需求选择动态图形的自然画布尺寸、时长、素材名称、描述和属性架构。素材时长应与预期放置时长一致,包括内部入场、停留和退场时序。素材创建步骤只会创建素材;时间线放置是单独的操作。
对于 create_motion_graphic_from_code,将自然画布尺寸作为 width/height 传入;只有在有意创建全画幅动态图形时才使用时间线尺寸。如果内容只占据屏幕的一部分,请使用 edit_item 放置并缩放有界素材,而不是将屏幕坐标写入全画布动态图形。
修补现有素材
修补前,先检查现有素材代码和属性架构。除非所请求的更改另有要求,否则保留无关行为、属性键和时间线时序。
通过当前素材更新工具,以完整的内联替换源代码进行修补。
放置到时间线
使用时间线编辑工作流进行放置、移动、修剪和实例级属性覆盖。如果工具支持验证,请对大型或不确定的事务进行试运行。
验证
工具调用成功并不代表已完成验证。
- 创建或更新素材后,重新读取素材状态。
- 放置、移动、修剪或覆盖属性后,重新读取时间线状态。
- 对于可见更改,请通过常规的 ChatCut 视觉验证流程检查实际合成帧。
- 对于批量操作,将合成后的稳定帧并排比较;确认每项视觉任务都有合适的形式,重复出现的表面、锚点和节奏设计合理,并且每个放置都适用于各自的目标帧。
- 如果结果有误,请先判断故障类型再重试:工具参数格式无效、JSX 无效、属性键缺失或不正确、时间线放置问题、素材异步就绪问题,或画布/导出安全问题。
create_motion_graphic_from_code或edit_asset返回的导出契约错误会列出浏览器导出无法绘制的样式;请改写这些样式后重试。旧版警告表示缺少renderContract(参见 Renderer CSS Support)。- 通过时间线编辑修复放置问题,通过 JSX/属性更改修复渲染问题。