Communitygithub.com

Morph Edit 动态图文编辑器

将说话人头视频及其文本稿转换为与演讲者话语同步的动态图形辅助素材,采用连续单一形状风格(一个元素不断变形,绝不剪切,由光标驱动,带有弹性动画)。适用于用户提供视频(最好还有文本稿)并要求制作动态图形、辅助素材、动画插页或叠加层时。

Morph Edit 动态图文编辑器 是什么?

Morph Edit 是一个针对视频创作者和 AI 智能体工作流的专业动态图形技能,能将说话人头视频及其文本稿自动转换为连续单一形状的辅助素材。核心创新在于每个剪辑都是一个从不剪切、持续变形的形状(大小、圆角、颜色),内容通过短暂模糊过渡,所有变化都精准对应到特定的口语词汇。该技能支持 macOS 和 Linux 平台,需要 Node.js、Python 3、FFmpeg 以及 Playwright + Chromium 环境。工作流程包括:询问用户视频和文本稿、设置密度和视觉风格、检查素材参数、规划镜头表、编写剪辑片段、构建静帧缩略图、渲染最终视频并交付 HTML 交付物(预览、分步查看、对比页面)。它还支持为 YouTube 等平台制作订阅结束卡片及生成多语言隐藏字幕,确保所有动画都以说话节奏和词汇为其时间锚点。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/mrgoraya/morph-edit/tree/main/skills/morph-edit

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Morph Edit 动态辅助素材(motion B-roll)

你为创作者的视频制作动态图形剪辑。每个剪辑都是一个从不剪切的形状:它在不同状态间变形大小、圆角与颜色,同时内容通过短暂模糊进行切换。一个光标通过真实的点击和拖拽驱动变化,且每个变化都落在某一个口头词语上。

输出是一组剪辑,创作者可直接拖入其编辑器。你还需提供一段将剪辑嵌入后的视频预览渲染,以及两个 HTML 页面:一个用于逐段查看剪辑,另一个用于对比原始与效果。

你所需的一切均在此技能文件夹中:

  • engine/:运动引擎 (motion.js)、页面外壳 (base.css)、build.py(将剪辑生成为独立 HTML)、render.js(帧逐帧渲染,含运动模糊)、beats.js(静帧接触表)、字体(Geist,OFL 许可)。
  • scripts/:setup.sh、inspect_video.py、words.py、composite.py、make_pages.py。
  • reference/engine-api.md:如何编写剪辑。在编写第一个剪辑之前请先阅读。
  • examples/opus-aoe2/:针对一个真实 54 秒视频的六个完成剪辑。请将其作为质量基准和起点。

下文中的 $SKILL 表示此技能文件夹的路径。请在用户项目的 motion/ 文件夹中工作。

1. 环境设置(仅首次运行)

bash $SKILL/scripts/setup.sh ./motion

该脚本检查 Node、Python 3 和 ffmpeg,并将 Playwright + Chromium 安装到 motion/node_modules。运行所有引擎脚本时请使用 NODE_PATH=./motion/node_modules。

2. 用户访谈

使用 AskUserQuestion 工具;仅限一轮。你需要了解:

  • 视频。一个路径。将其复制或引用为 motion/work/source.*。
  • 文本稿。可选。如果没有(或只有纯文本),请使用 scripts/transcribe.py 转录音频(参见步骤 3)。这会提供真实的词语时间戳,比 SRT 估计更精确。
  • 密度:
    • 轻度:每分钟 2–4 个剪辑,仅用于最强时刻。
    • 中度(默认):每分钟 4–7 个。
    • 重度:覆盖大部分台词,面部画面短暂出现。
  • 外观:
    • 默认调色板:暖灰画布、黑色和白色组件、一个橙色强调色。
    • 或使用他们的品牌:颜色,可选字体。请用户将Logo、截图或品牌色放入 motion/inputs/ 中,并读取它们。
  • 需要避免或包含的内容。 保留在面部画面的台词、需要显示的真实数字或名称、需要重新创建的产品截图。

跳过用户已经回答的任何问题。

3. 检查素材

python3 $SKILL/scripts/inspect_video.py motion/work/source.mp4 motion/work
python3 $SKILL/scripts/words.py transcript.srt > motion/work/words.txt
# 如果没有文本稿(或需要精确词时间):改用音频转录
motion/.venv/bin/python $SKILL/scripts/transcribe.py motion/work/source.mp4 motion/work

transcribe.py 会生成 words.txt 和 transcript.srt。向用户展示转录文本,以便他们在规划前纠正误听的名字或术语。

自己查看 motion/work/contact.png。video.json 提供分辨率、帧率和布局分区:

  • full: 演讲者充满画面。
  • pip: 演讲者位于小窗中,其余区域为空白。包括小窗位置以及当小窗大小或位置变化时的警告。

剪辑必须与视频的分辨率和帧率匹配。来自 SRT 的文字时间仅为估计值(±0.2 秒);请按此对待。

4. 规划并获得批准后再编写代码

显示一个表格,每行对应一个剪辑:

| # | 入点–出点 | 覆盖的台词 | 形状在哪些词语上做什么 | 处理方式 | 理由 |

创意方向:决定每个剪辑占据画面的多少。 这是最重要的决策;请对每个剪辑单独做出,并说明理由。

  • 全幅切换。 画面全部是演讲者,且台词描述的是需要看到的内容:产品、过程、对比、数字、章节变化。
    • 在创意持续期间(3–10 秒)切换走,然后切回面部。
    • 不要在钩子的第一秒、或涉及个人、情感、观点台词时切换。
    • 每次切换之间至少保留约 2 秒的面部画面。
  • 在空白区域放置面板。 编辑本身留有空间:画中画框、分割区域、纯色区域。
    • 渲染一个透明剪辑(bg:null),居中放置于空白区域,大小时刻与演讲者小窗保持距离。
    • 它可以持续较长时间(15 秒以上)作为单个连续变形,因为演讲者始终在屏幕上。
    • 如果 inspect_video.py 报告小窗尺寸变化,请询问这是否有意为之,然后选择最大尺寸或在变化点分割面板。
  • 不处理。 台词是关于演讲者的,或者与其他剪辑太接近。

内容规则:

  • 展示主题的真实对象:文件夹、终端、文件、产品、结果。从文字中提取它们。将每个想法映射到 reference/engine-api.md 词汇表中的互动(柱状+点击、进度、检查、状态岛、带拖拽的卡片、滑块、开关、标签页、图表+提示框、搜索/筛选、文件拖放、终端打字、并排对比、章节卡片)。
  • 切勿编造数字、引语、价格或结果。 使用相对条、骨架文本行或从转录中提取的标签,并列出哪些是示意性的。只有用户提供真实数据时才放入。
  • 每个剪辑一个想法。一个连续片段(如整个画中画区域)可以是一个包含多个状态的单个长剪辑。
  • 节奏跟随说话,而非音乐:每个口头节拍对应一次变化,间隔约 0.4–1.2 秒。

等待用户批准或修改规划。

5. 构建

在 motion/clips/NN-name.html 中为每个剪辑编写一个片段,遵循 reference/engine-api.md 和示例。然后构建:

python3 $SKILL/engine/build.py motion/dist motion/clips/*.html

将每个状态变化放在对应的词语上:剪辑本地时间 = 词语时间 − 剪辑入点。

6. 检查关键词语上的静帧

NODE_PATH=./motion/node_modules node $SKILL/engine/beats.js motion/dist/NN-name.html motion/work/NN.png 0.4 1.2 2.1 …

选择每个状态稳定后的时间点以及一些变形过程中的瞬间。亲自检查每个静帧表。修复任何拥挤、裁剪、不可读、偏离词语的问题,或光标移出画面的情况。然后再次检查。面板剪辑在静帧表中以黑色背景渲染,以便你判断。

7. 渲染

NODE_PATH=./motion/node_modules node $SKILL/engine/render.js motion/dist/NN-name.html motion/out/NN-name_0m32s40.mp4 30000/1001
  • 使用视频的帧率。
  • 面板剪辑(bg:null)必须保存为 .mov,这将生成含 Alpha 通道的 ProRes 4444。
  • 按时间线入点命名每个文件(0m32s40 表示 0:32.40)。
  • 渲染每帧耗时 4 个子帧,因此比实时慢。在多核机器上可并行运行两个剪辑。

8. 交付

编写 motion/plan.json(模式见 reference/engine-api.md)。对于 UI 音效,为每个剪辑提供 "sfx": [[剪辑本地时间, 类型], …] 列表,从提示中提取:click 和 toggle 在光标点击时、pickup/drop 在拖拽开始/释放时、whoosh 在形状变形时、pop 在介绍和徽章上、rise/fall 在柱状图上、type 在打字时、tick 在元素出现时、shutter 在截图时、success 在检查通过时。然后:

python3 $SKILL/scripts/composite.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/sfx.py motion/plan.json motion/out/preview.mp4   # UI 音效,如果用户需要
python3 $SKILL/scripts/make_pages.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/make_gallery.py motion/plan.json motion/out/preview.mp4

用户将收到(均在 motion/out/ 中):

  • 剪辑文件
  • TIMING.md:文件、入点、出点、覆盖的台词、处理方式、以及哪些是示意性的
  • preview.mp4:嵌入剪辑后的视频,硬切,原始音频(以及使用时带 SFX 的版本)
  • sfx/:每个剪辑的单独音效 WAV 文件,用于在编辑器中混音
  • index.html:所有剪辑同时在网格中播放,包含完整预览和指向其他页面的链接(先打开此文件)
  • viewer.html:逐段查看剪辑
  • compare.html:原始版本与预览版本同步对比,支持并排、堆叠或擦拭方式

明确说明预览仅用于审阅:最终剪辑时,他们需将剪辑放入自己的编辑器,在那里可以微调时间、添加过渡和混音。

订阅卡片(可选)

询问创作者是否希望在其行动号召台词上添加订阅结束卡片,以及一两条简短提醒。模板位于 $SKILL/templates/subscribe/(end-card.html、reminder.html)。将其复制到 motion/clips/ 中,然后:

  • 替换 __CHANNEL__、__HANDLE__ 和 __AVATAR__(创作者的Logo或照片作为 data URI;若无图片,则使用圆圈中的字母)。请询问这些信息;切勿猜测名称或句柄。
  • 根据创作者的实际话语重新调整 <script> 顶部的常量(IN、点击时间、T)。结束卡片在创作者说出词语时点击“分享”、“订阅”、“铃铛”、“点赞”和“评论”;提醒卡片点击“订阅”和“铃铛”。
  • 像其他剪辑一样构建、检查静帧、渲染并添加到 plan.json。将卡片渲染为透明 .mov 面板,以便叠加在素材上。

字幕(可选)

制作一个口语语言 SRT 和一个英文 SRT,用于上传为隐藏字幕(而非烧录)。在 motion/work/cap/ 中工作:

  1. motion/.venv/bin/python $SKILL/scripts/captions/find_gaps.py motion/work/words.txt "<video>":Whisper 可能在长视频上遗漏整段语音。它会打印出空白段;使用 retx.py "<video>" "<空白段列表>" motion/work/gapwords.json [语言] 重新转录这些空白段。
  2. python3 $SKILL/scripts/captions/make_cues.py motion/work/words.txt motion/work/gapwords.json motion/work/cap 写入提示信息和四个块。
  3. 使用 templates/caption_brief.md 并行翻译这些块(四个子智能体,每个块一个)。每个块写入 out1..4.json,包含每个提示的 {"i","orig","en"}。
  4. 修复标记的提示,然后 python3 $SKILL/scripts/captions/build_srt.py motion/work/cap motion/out/captions 写入 captions_original.srt 和 captions_english.srt(每行两个平衡句,最多 42 个字符)。
  5. 告知创作者在发布前在 VLC 或未公开上传中测试 SRT。

样式默认值

用户的品牌将覆盖这些设置。

  • 颜色: 画布 #E9E7E2,墨色 #0B0B0B,白色组件,一个强调色 #FF5A1F。深色素材上的面板剪辑使用浅色形状(#F4F2EE)。
  • 字体和图标: Geist 用于 UI 文本,Geist Mono 用于代码、文件名和终端。一组图标,统一描边宽度(M.icon)。
  • 运动: 弹簧动画,至多轻微过冲。前缘和后缘使用不同的弹簧,因此指示器会有拉伸。相机缩放以使每个状态充满画面。
  • 禁用: 弹跳缓动、粒子、发光、UI 镀铬上的渐变、混合图标描边、空闲时间、任何看起来像模板的东西、虚构的数据。

常见问题

  • 切勿在相机缩放的任何东西上设置 will-change,否则文本渲染模糊。
  • 在变形容器内切换文本需要其自身的进入和退出时间(M.vis din/lin/lout),否则新旧文本会重叠。
  • 使用 mix-blend-mode: difference 的标签必须位于具有混合模式本身的图层中。过滤后的父元素会隔离它们。
  • 在高亮下滑动的项目需要使用 M.FAST 弹簧,否则高亮行会短暂空白。
  • 在每次相机缩放时保持光标在画面内,包括变形过程中。
  • 来自 SRT 的词语时间在提示内会漂移;尽量将重要变化放在提示的第一个或最后一个词语上。
  • 剪辑通过保持其最后一个状态结束;如果合成时间段更长,合成器会保留最后一帧。

相关技能