动画视频广告
将产品视频的每一个镜头构建为一个小的 HTML 页面,该页面动画展示真实的产品素材(截图、视频帧、导出的数据、实际数字),将每个页面录制为干净的 MP4,并交给用户一份脚本文档,明确告诉他们如何拼接剪辑片段以及该说什么。用户在自己的编辑器(Camtasia、Premiere、CapCut...)中拼接剪辑并录制旁白。
为什么这比直接屏幕录制真实应用更好:每个镜头都经过完美框架、节奏和缩放;没有闪烁、加载或显示私有数据;文字足够大,适合手机观看;一旦需要修改(“让那行更短”、“放慢缩放速度”),只需编辑并重新录制,无需重新拍摄。它看起来仍然真实,因为像素和数字都来自产品本身。
工作流程
- 确定故事(一条消息,然后开始)。
- 从产品收集真实素材。
- 从
assets/为每个镜头构建一个页面。 - 通过截图检查页面,修复问题,重复直到满意。
- 使用
scripts/record.cjs录制剪辑;通过联系表验证。 - 编写脚本文档(
references/script-doc.md)。 - 音频和粗剪: 音乐(ElevenLabs、生成或用户自有;
references/music.md),可选的 ElevenLabs 旁白(references/voiceover.md);使用scripts/roughcut.py预览。 - 发送剪辑、文档和预览;根据反馈逐个镜头迭代。
将所有内容放在用户拥有的一个文件夹中,例如 video/ 或 video-scripts/:
<名称>-anim/ 页面(每个镜头一个 .html),base.css,logo,frames/ 子文件夹
<名称>-clips/ 录制的 MP4:01-hook-anim.mp4, 02-setup-anim.mp4 ... + README.md
<名称>-music/ 背景 WAV,粗剪预览,cuts.json
<名称>.md 脚本文档
1. 故事
选择长度(默认 30 秒;提供从相同剪辑制作的 45–60 秒版本)以及行动号召。
根据广告投放平台选择画面比例,并按此尺寸构建页面(不是后期裁剪为 16:9;裁剪会丢失文字,且用户必须重新调整每个镜头):
| 投放位置 | 尺寸 |
|---|---|
| Instagram Reels/Stories, TikTok, YouTube Shorts, Facebook Reels | 1080×1920 (9:16) |
| Instagram/Facebook 信息流 | 1080×1350 (4:5) |
| LinkedIn 或 X 信息流 | 1080×1080 (1:1) 或 1080×1350 |
| YouTube, 网站, 落地页, 演示, 未指定 | 1920×1080 (16:9) |
多个投放位置:为主投放位置构建,并在文档中说明如何为其他投放位置重新框架。对于竖屏,请将文字保持在顶部约 250 px 和底部约 350 px 之外,因为这些位置平台会绘制自己的 UI。然后以如下结构概述 6–9 个镜头,每个一个创意:
- 钩子(约 3 秒): 用观众的语言描述问题。一个问句就很好(“30 天后发票仍未支付?现在怎么办?”)。
- 设置(约 4 秒): 开始使用需要多小的步骤。
- 核心功能(2–3 个镜头,每个 4–5 秒): 产品完成其工作的过程,结果落在屏幕上。
- 证明(约 3 秒): 一个真实的数字。大,简单,真实。
- 融入你的工作流程(约 3 秒): 导出、集成、共享。
- 结束卡片(约 3 秒): 标志,一句承诺,行动号召按钮,URL。
用积极的方式引导。 展示产品做得好以及有多简单。不要围绕产品的失败案例或变通方法构建镜头,即使是一个巧妙的变通方法;一个解释工具在错误时如何应对的广告会让人觉得“它经常出错”。用户快速、自信的修复(“分类错了?点击它,选择正确的,完成”)是可以的;但关于边缘情况机制的镜头则不行。
如果用户没有说明,用一条简短消息陈述你的概要假设并开始构建;更改一个已录制的镜头比在抽象层面讨论它更便宜。
在相同消息中,询问音频(除非他们已经说过),并在他们决定时继续构建;音频直到第 7 步才需要。如果存在,使用提问工具。首先检查 ElevenLabs MCP 是否已连接(工具如 creative_generate_speech、creative_list_voices、music 节点类型);如果已连接,优先使用它。
音乐:
- ElevenLabs Music(推荐,当已连接): 你生成一个与剪辑时间相匹配的纯音乐背景,使用他们的 ElevenLabs 帐户。未连接:你编写提示词,他们在 elevenlabs.io/music 生成并返回文件。
- 在此生成: 一个安静、免费许可的背景音乐,由
make_bed.py制作,免费且即时。 - 自带曲目: 用户已有的或已获得许可的音轨。
旁白:
- ElevenLabs 语音(当已连接): 你选择一个语音并生成朗读,然后将每句台词放在其提示点。用户仍然可以在之后自己录制。
- 用户自行录制: 根据文档中的清晰朗读版本录制(没有 ElevenLabs 时的默认情况)。
ElevenLabs 会消耗其账户积分:先估算价格(estimate_only)并在问题中说明成本。如果他们要求音乐但未指定类型,或者你进行到第 7 步而没有回答,则生成免费背景音乐以使预览有声音,并在最终消息中重复提问,同时已写好 ElevenLabs 的提示词。
2. 真实素材
在产品的代码仓库、数据文件夹、导出文件、数据库、测试固件和录屏中查找。对于每个镜头,收集:
- 图片: 真实 UI 的截图,或从真实视频中提取的帧(
ffmpeg -ss T -i in.mp4 -frames:v N frames/f%03d.jpg)。多个帧可以创造运动效果。要对 Web UI(本地 HTML 或 URL)进行截图,使用scripts/grab.cjs:全视图加上命名元素(3 倍缩放),并打印每个元素的框以进行框架定位:node <skill>/scripts/grab.cjs app.html <pages>/shots --size 1280x800 goal=.goal logo="header .logo"。如果位于登录后,请要求用户提供截图,不要自行登录。 - 数字: 产品输出的实际值(时间、计数、行数)。记录每个数字的来源;它们将进入文档的“数字来源”部分。
- 位置: 需要高亮的事物的坐标,以源图像的像素为单位(尽可能来自应用本身的输出,例如检测框,或通过查看图像测量)。
存在差距是正常的;公开处理:
- 没有 Logo 文件: 从真实 UI 截图(头部、应用图标)中裁剪,或根据产品自身的 CSS/SVG 精确重建。在文档中说明并要求提供真实文件。
- 需要的屏幕在你拥有的素材中不存在(例如一个设置表单):以产品自身风格绘制它,并在文档中将该镜头标记为“模拟”,以便用户可以用真实屏幕替换。
绝不虚构统计数字。如果某个时刻必须模拟(例如戏剧化的钩子),在文档中标注。尊重产品自身的术语和声明规则(例如,一个产品绝不能称其数字为“保证”或“官方”)——在编写文案前,检查项目文档/记忆中有无此类规则。
3. 构建页面
将 assets/base.css、assets/shot.js、assets/shot-template.html 和 assets/end-card.html 复制到页面文件夹中。shot.js 包含每个页面使用的辅助函数(show/hide、cursorTo、click、typeText、countUp、frameTo、preload)和自动播放功能;在页面自己的脚本之前加载它,不要将辅助函数复制到页面中。每个页面:
- 是在所选尺寸下的固定舞台:在
base.css中设置--w/--h(例如1080px/1920px)。模板默认布局为 16:9,因此对于其他画面比例需要重新定位布局(对于 9:16 竖屏,竖直堆叠面板;在竖屏上,标题从约 250 px 以下开始,而不是模板的 96 px)。文字大小 ≥ 26 px;标题 80–100 px。它将在手机上观看。 - 有一个顶级
async function start()函数,包含整个时间线(在节拍之间使用await sleep(ms))。shot.js暴露它;在 URL 中包含#manual时它会等待,正常打开时会自动播放(一旦字体和图像准备好),因此用户可以通过双击预览。 - 预加载稍后要切换的每一个图片(在顶层使用
preload(frames)),因此不会在录制时突然出现;录制器和检查器会等待它们。 - 以一个稳定的、完整的最终状态结束(显示结果,所有文字显示),以便编辑器可以在接近结尾的任何位置进行修剪并保持最后一帧。
- 在
<svg viewBox="0 0 W H" preserveAspectRatio="xMidYMid slice">中绘制标记,该 SVG 的大小与源图像匹配,因此应用坐标可以直接使用而无需转换,并且在舞台形状裁剪图片时仍能保持对齐。 - 看起来像产品本身:替换
base.css中的令牌(--accent、--hi、--ok、--ink、字体)为产品自身的颜色和字体。对于浅色主题的产品,还需要将文字颜色、.shade、.panel和.bg切换为浅色版本;一个深色广告搭配浅色应用看起来像是别人的产品。 - 在
.world内部以原始像素大小显示 UI 截图(设置.world { transform-origin:0 0 }并将<img>设置为其自然的 CSS 大小),并使用frameTo(x, y, scale)对其框架定位,该函数将截图点 (x, y) 放在舞台中心;grab.cjs的框提供点。不要使用object-fit:cover,因为当截图形状与舞台不匹配时,它会不可预测地裁剪截图。 - 保持产品文字可读:在舞台上最终小于约 22 px 的 UI 文字(例如截图中 14 px 的标签且未放大)在手机上无法阅读。放大该文字,或者以产品自身风格重建该部分(一个卡片、一个警告框),使用其确切的文字和可读的大小,并在文档中说明哪些部分被重建。
已验证有效的镜头模式:
| 模式 | 如何实现 |
|---|---|
| 产品在行动 | 每 33–40 毫秒在 <img> 中切换帧序列,每帧绘制框/标签,结果行在发生瞬间弹出到侧面板。 |
| 缩放到细节 | .world 在细节上设置 transform-origin,添加 .zoom(缩放 1.5–1.6,1.2 秒缓动)。 |
| 用户执行步骤 | await cursorTo(button) 然后 await click(button):光标滑向元素测量中心,涟漪,按钮按下,然后显示结果。使用 typeText(el, text) 打字(每个字符 55 毫秒;保持任何打字字符串不超过约 1 秒)。 |
| 逐帧浏览 | 按节奏按下上/下一帧按钮,帧计数器显示,关键帧被标记。 |
| 两个视图一致 | 两张图片并排,同一时刻在两者中标记,一个徽章显示一致性。 |
| 证明 | 表格行滑入(相隔 120 毫秒),然后 2–3 个统计卡片;使用 countUp(el, n) 计数核心数字(约 700 毫秒)。 |
| 数据输出 | 结果列表和文件/集成面板在同一节拍中填充,带有“实时”指示器。 |
| 结束卡片 | 线条扫过,标志,标语,行动号召按钮弹出,URL。 |
将光标指向元素,而不是手动输入的坐标:cursorTo(el) 在光标移动时测量元素,因此缩放、重新布局或其他舞台形状不会导致光标点击空区域。如果提示不在 el 上,click(el) 会记录错误,并且 check.cjs 在此情况下会失败。仅在没有元素时使用 cursorTo({x, y})。在每次点击的时刻拍摄检查截图:一个准确落点的点击是观众唯一会注意到是否错误的事情。
使用 shot.js 中的 show(el) / hide(el) 显示和隐藏。.on 使用 !important,因此任何其他添加到它旁边的用于隐藏或移动元素的类都会静默无效;始终先移除 .on(这就是 hide 所做的)。对于自定义退出效果,使用 el.classList.replace('on', 'my-exit')。
保持时间线紧凑:节拍之间 0.3–0.7 秒,阅读一个标题约 1 秒。每个剪辑通常 4–8 秒;一个逐帧浏览的镜头最长可达 15 秒,因为编辑器会修剪并加快其速度。
裁剪源素材中不应显示的任何内容(相机日期/时间、状态栏、私人名称)——通过从对侧边缘稍微缩放 .world 来实现(例如从底部 scale(1.08))。不要依赖 backdrop-filter 来隐藏事物:它在屏幕录制中不会渲染。
4. 录制前检查
node <skill>/scripts/check.cjs <pages-dir> <chk-dir> hook:400:1500:3200 live:800:3000:6000
在 start() 之后的那些毫秒处拍摄截图(它故意不等待 start();等待只会显示结束状态)并打印页面错误。阅读截图。特别检查:
- 标记位于正确的位置(框在正确的人身上,线条在领先边缘上,而不是后续的脚或旁观者;检测器轨迹可能在序列中途切换到其他人,因此需要拼接或手动修复框);
- 没有内容被边缘裁剪,文字不与主体重叠;
- 屏幕上的每个数字都与来源匹配。
5. 录制
node <skill>/scripts/record.cjs <pages-dir> <clips-dir> hook=01-hook-anim=4200,setup=02-setup-anim=5000
page=outName=ms:录制 ms 持续时间(动画长度 + 约 1 秒的保持结束)。每个剪辑以其页面的尺寸(--w×--h)、30 fps、H.264 CRF 16、静音格式输出。check.cjs 和 roughcut.py 遵循相同尺寸,因此竖屏或方形无需编辑脚本。需要 Chrome(或 Playwright 的 Chromium)和 Playwright(如果 pw.cjs 找不到,可运行 npm i -g playwright),以及 ffmpeg。
剪辑运行请求的毫秒数加约 0.3 秒。第一帧是 start() 的第一个节拍之前的页面,因此切入时间通常从 0.1–0.3 秒开始;从联系表中读取。
无需观看即可验证每个剪辑:
bash <skill>/scripts/sheet.sh <clips-dir>/03-live-anim.mp4 sheet.jpg 2
阅读联系表:每个节拍的时机,没有内容被压扁或裁剪,最后一帧完整。记录每个剪辑有用部分的切入/切出秒数;它们将进入剪切表。
按故事顺序命名剪辑 NN-name-anim.mp4(用 04b、04c 表示备选),并在剪辑文件夹中编写一个简短的 README.md 列出它们。
6. 脚本文档
遵循 references/script-doc.md。剪切表(时间、剪辑、切入-切出、速度、你看到的内容、旁白开始、台词)是其核心;其余内容为用户提供无需你也能完成所需的信息。旁白:约每秒 2.5 个词,对话风格,每个镜头一行台词,行动号召大声说出(“免费试用。点击链接,或访问 example.com。”)。
大多数社交视频在静音状态下被观看,包括 Reels 和 TikTok。始终为剪切表提供一个“屏幕上”列,并使屏幕上的文字本身能够传达故事。在有旁白的情况下(Reels、TikTok、Shorts),还要在编辑器步骤中添加烧录字幕,放置在竖屏安全区域内,并放在其标题已经...
…(内容已截断,供翻译)