mcpField
C
create-motion-graphics

create-motion-graphics

github.com/chatcut-inc创意与媒体988156 次安装今天更新
代码仓库

关于 create-motion-graphics

create-motion-graphics 是面向 ChatCut Web 编辑器的技能,用于通过 JSX 创建或修改 Motion Graphic 素材。它要求依据项目样式、画面与内容选择参考,并检查图形在实际镜头中的效果。

主要功能

  1. 01浏览并选择视觉样式与图形参考
  2. 02根据项目样式编写或修改 JSX 图形
  3. 03将可变文字、颜色和数值设为可编辑属性
  4. 04依据镜头与语音确定构图和时长
  5. 05修改后检查项目状态与画面效果

适用场景

  1. 01为视频制作与项目风格一致的动态图形
  2. 02调整现有 Motion Graphic 的文本或视觉属性
  3. 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 效果一致。

  1. 从当前项目的 browse_assets 中复用素材。仅将输出所需的制作文件导入 My Assets。加载 asset-import,并使用其 import_media 会话/上传辅助工具。注册项目媒体不会将其发布到公共资源库。
  2. 使用 edit_item 放置常规制作媒体,并使用返回的当前项目素材 ID。Agent 负责将示例人物、文案和数据替换为当前任务的内容。不要将参考图中的完整效果截图用作背景。
  3. 仅当视觉效果机制需要时,才将媒体嵌入 MG,例如图像填充文字,或可用时间线工具无法实现的紧密同步内部蒙版。对于此类例外情况,image/video 属性的默认值和覆盖值必须绑定到完整的当前项目素材 ID,不得使用 URL、本地路径或参考库 ID。通过 item.props 读取,处理空值,并让运行时解析来源。声明图像属性并不会导入文件。
  4. 在入场帧和稳定帧检查合成时间线,包括媒体是否存在、裁剪、效果、图层顺序和时序。独立的透明 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>;
};

动态图形代码规范

违反规范会导致运行时崩溃。必须严格遵守。

  1. 语法: 纯 JavaScript JSX。不使用 TypeScript。
  2. 导入: 不使用 import 语句。以下全局变量已预先注入:React、spring、useCurrentFrame、useVideoConfig、interpolate、interpolateColors、Math、random、Easing、AbsoluteFill、Sequence、Series、Img、Video 和 Audio。
  3. 使用注入的全局变量: 可直接使用 Hooks 和组件;不要通过命名空间对象访问它们。
  4. 导出: 不使用 export default。定义 const Component = ...。
  5. 时间控制: 组件内部不要使用 Sequence 包装器。使用扁平的帧驱动逻辑。
  6. 逻辑: 不要在 JSX 属性中内联逻辑。在 return 之前将值预先计算到变量中。
  7. 辅助函数: 不要使用未定义的函数。使用复数形式的 interpolateColors。在本地定义所有辅助函数。
  8. AbsoluteFill: AbsoluteFill 是组件,不是样式对象。绝不要展开它。可以将它用于内部图层,但绝不能将它用作根元素。
  9. 根元素: 根元素必须是 <div style={rootStyle}>。
  10. 素材: <Img> 和 <Video> 的来源必须读取图像/视频可编辑属性。绝不要硬编码 URL。如果没有提供素材,请使用形状、文字和 CSS 进行设计。
  11. Hooks: 使用 useCurrentFrame() 获取帧,而不是 useVideoConfig()。
  12. 局部盒子: 组件必须接受 ({ item }) 属性。素材的 width/height 是 MG 围绕其可见局部构图的自然盒子,不是时间线画布;使用 position:absolute; inset:0 填满该盒子。时间线布局会设置最终屏幕尺寸和位置。
  13. 布局控制: 使用 flexbox 或 grid 布局文本块和结构化内容。如果设计依赖空间关系、复合形状、边框效果或绘制/动画标记,请使用 SVG 或绝对定位几何布局。除非需求要求文本单行显示,否则应允许文本自然换行。
  14. 可编辑属性: 组件必须从 item.props 读取可编辑值。props.key 后绝不要添加 || "Default" 或 ?? false 等回退值;已声明的运行时属性已有对应值。
  15. 属性架构: 声明匹配的可编辑属性。包含所有可见文本内容以及主色/强调色。
  16. 图像/视频属性: 在媒体属性中存储项目素材 ID,从 item.props 读取运行时值,并且仅当该值为真值时才渲染 <Img>/<Video>。
  17. 背景: 默认背景为透明。如果添加背景表面,请提供一个 transparentBackground 布尔属性。
  18. 导出成本: 保持内联 <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。替代方案:在内容后方放置一个 README 配图。
  • 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/属性更改修复渲染问题。

评论

支持 Markdown