Communitygithub.com

kb114/motion-ad-studio

用于制作短视频动态图形广告或宣传片(9:16 Reels/TikTok/Shorts、4:5 信息流)。构建可调试的 HTML/GSAP 动画,每个动作与旁白词语和音乐节拍锁定,通过脚本校验,并在每次运行中自我学习。可选配 ElevenLabs。

motion-ad-studio 是什么?

Motion Ad Studio 是一个自优化的 AI 技能,专用于生成专业级动态图形广告短片(20-40 秒),主要面向竖屏短视频平台(Reels、TikTok、Shorts)和 4:5 信息流广告。它通过单个 HTML 页面(GSAP 时间线 + 纯时间函数)构建逐帧精准的动画,并与 MP4 渲染引擎配合,确保画面与旁白、音乐节拍精确同步,包含一整套质量检测脚本(视觉检查、几何探测、转场速度匹配门控、音视频合规检查),覆盖从创意构思到交付的完整流程。该技能支持 ElevenLabs 实现高质量语音合成和音乐生成,也提供本地预处理方案(如合成背景音乐),并记录每次运行的经验教训到 `references/lessons.md` 和 `references/runs.md`,从而实现持续自我改进。适用于希望高效产出高一致性、高节奏感的品牌推广视频的开发者或创意团队。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/kb114/motion-ad-studio/tree/HEAD

在你喜欢的 AI 中提问

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

文档

Motion Ad Studio(自我优化版)

制作一段 20-40 秒的竖屏动态图形广告,达到资深动态设计师认可的标准:第 0 帧即开始运动,整体有一条贯穿的载体对象,转场在运动中途发生并速度匹配,每一次点击、着落、坠落和呼啸声都与旁白词语或音乐节拍锁定。影片为单一 HTML 页面(GSAP 时间线 + 纯时间函数),可逐帧渲染为 MP4,并在任何人观看前由脚本进行校验。音效源自影片自身的事件列表,因此音频同步由设计保证,而非靠耳朵调节。

每次运行:先阅读 references/lessons.md 和 references/runs.md。结束时执行回顾(第 13 步)。 技能会持续改进,但前提是你将经验教训写回文件中。

0. 预检(始终执行)

python scripts/preflight.py [--elevenlabs-mcp yes]   # 如果你已连接 ElevenLabs 工具,则传 yes

以下路径相对于本技能文件夹($SKILLS/motion-ad-studio):scripts/...、references/... 和 templates/...。$MOTIONMAXXING 是引擎文件夹($SKILLS/motionmaxxing;预检脚本会打印它),$SEAM_GATE 是可选的转缝门控脚本,预检脚本会找到它(或通过 --seam-gate FILE 指定)。

需求原因缺失时处理
motionmaxxing 引擎 (Apache-2.0)render.mjs(帧→MP4)、look.py 门控、lint.mjs 设计检查、runtime/vendor/gsap.min.js在本技能旁执行 git clone https://github.com/Tejashmakwana/motionmaxxing,或设置 MOTIONMAXXING
ffmpeg + ffprobe、Node 18+、Chrome/Chromium/Edge渲染、探测、混音安装;如果 Chrome 未自动找到,设置 CHROME_PATH
Python 3.9+ 及 numpy + Pillow节拍、合成背景音乐、混音、拼版pip install numpy pillow
faster-whisper(可选)为词语锁定时序提供词语时间戳pip install faster-whisper,或任何能输出词语起始/结束时间的对齐工具
转缝门控(可选)证明每个转场速度匹配HyperFrames motion-doctrine + patches/seam-gate-camera-overlap.patch
ElevenLabs(可选,推荐)富有表现力的语音、合成音乐、自定义音效请参阅下一节

ElevenLabs 是可选的:通知用户一次,绝不阻塞

如果预检脚本打印了通知(无 API 密钥且你未连接 ElevenLabs 工具),请用用户语言在音频步骤之前一次性简短告知,并让他们选择:

  • 连接:用户添加 ELEVENLABS_API_KEY 或连接 ElevenLabs MCP 服务器,然后重新运行预检。
  • 继续:使用下方无密钥路径构建完整影片。在交付说明中提一次,如果使用 ElevenLabs 能提升语音和音乐质量。同一项目中不再询问。 如果你无法询问(批处理或非交互式运行),则跳过,并将建议写入 NOTE.md。
层级使用 ElevenLabs不使用(仍可交付)
旁白带情感标签的 TTS,录制两次,选择其一用户自己的录音(最佳),或本地/操作系统 TTS 引导语音;或者无旁白的音乐主导影片
音乐根据影片长度、BPM 和“高潮点秒”生成音乐scripts/synth_bed.py(程序化生成,精确节拍网格),或用户拥有版权的曲目
音效1-3 个主样本(鞭子声、呼啸声、打字声)scripts/mix_events.py 本地合成所有音效
词语时间带时间戳的语音转文字(或 TTS 时间戳)scripts/words.py(本地 faster-whisper)

细节、提示、信用费用和许可规则:references/audio-providers.md。

流程

  1. 工作区。 python scripts/new_film.py <project> 复制单次拍摄工具包、GSAP 运行时和本地字体。渲染未改动 demo 的一帧以验证工具链:node $MOTIONMAXXING/scripts/render.mjs <project>/film/index.html --still 1.2,16.4 <project>/stills。

  2. 品牌工具包。 从用户处获取官方标志文件,并裁剪到其 alpha 包围盒。如果载体将停靠到标志中,则测量子字形矩形。通过统计网站 CSS 中的 #hex 获取颜色,并将字体作为本地 woff2 获取(scripts/fetch_fonts.py)。使用品牌实际使用的 CTA 渠道。绝不重绘或近似标志:必须向用户索取。

  3. 一个创意 + 一种新风格。 只写一个只有该品牌能拍的创意。覆盖标志测试:隐藏标志后,影片仍应指向该品牌。写出三个方向,删掉两个,选择一个与 references/runs.md 最后一行不同的风格。

  4. 钩子。 写 3 个 12 字以内的变体(问题、否定、具体性、故事),选一个。第 0 帧已活跃且运动,钩子在帧 1 前出现在屏幕上,没有从黑色淡入。

  5. 旁白。 约 2.5 词/秒(30 秒 ≈ 70-75 个词)。如果 TTS 支持情感标签,为每行标注([好奇] [自信] [有力] [俏皮] [温暖])。生成或录制,修剪长停顿,用 atempo ≤ 1.1 调整至合适长度,然后获取词时间:python scripts/words.py audio audio/vo.wav --lang <code>。Whisper 只给出时间。字幕文本始终来自已批准的脚本。

  6. 音乐。 生成(长度 + BPM + “高潮点在 处”)、授权曲目,或运行 python scripts/synth_bed.py --bpm 120 --dur 32 --drop 15.8 --out audio/bed.wav。用 python scripts/beats.py audio/music.mp3 audio/beats.json 获取节拍网格(synth_bed 会写入精确的 .beats.json)。修剪音乐头部,使高潮点落在旁白的高潮词上:影片节拍 k = first_beat - trim + k·period。

  7. STORYBOARD.md + ledger.json(templates/one-take/ 有填充的示例)。包括:

    • 页面规格、创意和三个方向;
    • 节奏表(时长段 / t / 能量 0-10 / 路线 / 音乐);
    • 时序映射:每个事件及其锁定的词 w(i) 或节拍 beat(k);
    • 旁白和示例数据列表;
    • ledger:每行一个转缝(退出/进入轴 + 方向、切割时间)。
  8. 构建。 从工具包中复制模式(references/one-take-kit.md):

    • 时钟 w(i) / we(i) / beat(k);
    • 每帧顺序 tl.seek → PRE(相机、移动锚点)→ cursors(读取实时 DOM 矩形)→ UP(跟随的 UI);
    • 关键帧 3D 相机和针对实时 DOM 矩形的光标引擎;
    • 纯 t 函数的打字/文本/类更新器;
    • sfx() 事件和源自相机的呼啸声。

    渲染器需要满足的约定:#main 带有 data-composition-id="main" data-width data-height data-duration。window.__seek / __duration / __timelines / __events / __player / __ready / __playerReady / __renderReady。蒙太奇风格影片(分层场景、扁平 UI、标志载体):references/montage-kit.md。

  9. 查看。 渲染 15-20 帧(node $MOTIONMAXXING/scripts/render.mjs ... --still t1,t2,... stills),拼成缩略图(python scripts/sheet.py stills sheet.jpg 6 220),进行一次视觉检查:每帧一行,然后是缺陷列表。修复并重复 2-3 次。

    • 几何真相(内容位置、可见性、透明度)来自 node scripts/probe.mjs index.html "t1,t2" "#a,#b"。
    • 文本真相来自全分辨率裁剪:视觉检查会误将缩小后的阿拉伯语和 CJK 文本读作“错别字”,但实际上并不存在。
  10. 转缝门控(推荐)。在 localhost 上提供影片文件夹,然后运行 node "$SEAM_GATE" verify --ledger ledger.json --url http://127.0.0.1:<port> --comp-url http://127.0.0.1:<port>/index.html。目标是 0 FAIL。如果单次拍摄相机甩动使两个窗口都在屏幕上,则需要在 "overlap": "camera" 及 patches/ 中的补丁。之后停止服务器。参见 references/qa-gates.md。

  11. 混音。 每个音效位于 window.__events({t, type:'sfx', name, gain, dur?, speed?})。

    • 使用 node $MOTIONMAXXING/scripts/render.mjs index.html --still <t> ev 导出,这会写入 ev/events.json。
    • 混音:python scripts/mix_events.py --events ev/events.json [--vo vo.wav --vo-at 0.10] [--music bed.wav --music-trim s] --dur <s> --out audio/mix.wav [--music-db -24] [--tp -2.5] [--whip/--whoosh/--typing samples] [--lift t0:t1:dB] [--fade t]。
    • 电平:VO 在 -18 dBFS RMS,音乐在 -30,在 VO 下进行闪避,呼啸声峰值与相机最快帧对齐,两次 loudnorm 处理到 -14 LUFS / TP ≤ -1。
  12. 渲染 + 门控 + 交付。

    • 渲染:node $MOTIONMAXXING/scripts/render.mjs index.html <新名称>.mp4 --audio ../audio/mix.wav --crf 17 --grain 0.03。每次尝试使用新输出名称:两次渲染到同一文件会导致损坏。
    • ffmpeg -v error -i x.mp4 -f null - 必须无输出。然后运行 python $MOTIONMAXXING/scripts/look.py x.mp4 --out look --expect <dur> --expect-audio(G0/G2/G3/G5 PASS)和 node $MOTIONMAXXING/scripts/lint.mjs index.html。
    • 交付:9:16 主版本、4:5 裁剪版本(布局确认后 crop=1080:1350:0:200)、2-3 个封面 PNG、NOTE.md(创意、时序映射、真实 vs 示例数据、音频来源 + 许可、门控编号、改进方向)及一个 project/ 文件夹(影片 + 音频 + 脚本)。
    • 清理:停止服务器和孤立的 headless Chrome。
  13. 回顾(必须执行,在最终回复之前)。 将带有日期的规则+经验教训追加到 references/lessons.md。在 references/runs.md 中添加一行(日期、产品类型、风格、长度、门控编号、已知后的结论)。如果有步骤变更,修补此文件、某个脚本或工具包。当用户稍后反馈时,记录结论。经验教训只包含方法,不包含客户名称或私有数据。

质量标准

  • 钩子: 真实客户用语或好奇心缺口。第 0 帧即运动,钩子在第 1 帧前可读,无黑色淡入。
  • 连续性: 整部影片有一条载体(光标、芯片、标志标记),无交叉淡入淡出,2-3 种转场类型重复使用。剪接在运动中途发生且速度匹配。保持一个当前方向:对于“下一个”,RTL 影片内容从左向右运动,LTR 影片从右向左。保留的向量用于表达含义。
  • 时序锁定: 每一个点击、坠落和着落都落在 w(i) 或 beat(k) 上,音乐高潮点落在旁白词上。呼啸声源自相机速度。时序映射列出每个事件及其锁定的内容。
  • 无无聊晃动: 每个停顿时都有带有意图的相机运动、阶段性揭示或实时 UI。静止只属于高潮前的时刻。
  • 安全区域 (1080×1920):
    • Meta 付费投放:可读文本在 y 270-1250 和 x 60-960(右侧 120 px 为按钮);
    • 自然 Reels/TikTok:保持底部 320-370 px 清晰;
    • 将字幕导轨放在 UI 面板下方,绝不覆盖构图器;
    • 字幕导轨显示图片已有的内容。
  • 结尾: 品牌标志加上一个品牌实际使用的 CTA。结尾持续 0.6-1.4 秒,最终镜头不超过影片长度的 25%。
  • 诚实: 在 NOTE.md 中声明示例数据。绝不捏造性能声明、价格或推荐语。
  • 目标: look.py G0/G2/G3/G5 PASS,运动能量 ≥ 5/255 平均亮度变化(深色 UI 影片接近 2),剪辑同步 ≥ 35%(实测专业基准),-14 LUFS ± 0.5,真峰值 ≤ -1 dBTP,0 个解码错误。

平台注意事项

  • Windows git-bash 上的后台任务:调用 node.exe,而不是 node winpty 别名(“stdin is not a tty”)。
  • 绝对 Windows 路径的 ESM 导入需要 file:///C:/...。
  • Headless Chrome 在中断运行后会泄漏。在最后,列出使用 --headless=new 和 --remote-debugging-port=0 启动且父进程已消失的浏览器,并杀死其根进程及其树。
  • 渲染速度:扁平 UI 在 1080×1920 下约 4 分钟每 35 秒。3D 世界约 4-5 分钟,约 4 fps,但前提是 3D 层数保持较少。

文件

  • scripts/:
    • preflight.py:依赖项和 ElevenLabs 通知;
    • new_film.py:创建项目脚手架;
    • fetch_fonts.py:本地 woff2;
    • words.py:词语时间;
    • beats.py:节拍网格和高潮点;
    • synth_bed.py:无密钥音乐;
    • mix_events.py:事件驱动混音;
    • sheet.py:缩略图拼版;
    • probe.mjs:实时几何探测。
  • templates/one-take/:完整的单次拍摄 3D 相机影片,作为可运行示例(虚构产品,阿拉伯语 RTL 文字),包含 STORYBOARD.md 和 ledger.json。
  • references/:
    • research.md:领域调查、上游技能、安全说明、平台规格;
    • lessons.md、runs.md:自学习记忆;
    • audio-providers.md、one-take-kit.md、montage-kit.md、qa-gates.md。
  • patches/seam-gate-camera-overlap.patch:用于单次拍摄相机影片的可选用转缝门控规则。

相关技能