---
name: motion-showreel
description: 用代码制作以图形、文字或界面动画为主的短视频（常见 5–60 秒，纯音乐片最长约 2 分钟），输出 MP4 和可编辑源码：产品宣传短片、动效作品集、UI 动效演示、动态排版与金句卡点、Logo 演绎与片头、生成艺术循环、年代回顾短片。配乐可选：代码合成，或按用户提供的曲子卡点。用户想做这类短视频或动效时使用，例如「做个 15 秒动效视频」「做个 Logo 动画 / 片头」「做个产品宣传短片」「用代码做视频」。不用于：口播讲解类长视频、网页与交互原型、写实人物或实拍内容、剪辑已有视频。
---

# Motion Showreel

把一个想法做成一支以图形、文字或界面动画为主的短视频，交付 MP4 和能重建的源码。

**原理**：页面暴露确定性的 `render(t)`，脚本逐帧截图，再用 ffmpeg 合成 MP4。配乐和音效在代码里合成，和画面共用一张时间表 `timeline.js`，所以卡点可以精确到帧。

**好片子从哪来**：变化密度、运动质感、一个记忆点、音画关系，这四项通常决定观感。但具体怎么动、动多少，由**风格和内容**决定，不是每支片子都要多机位、弹簧和满屏音效。全局只守几条底线（见「底线」），其余都是给模型的起点，不是天花板。

---

## 适用范围

| 用户想要 | 用这个 Skill？ |
|---|---|
| 产品宣传短片、动效作品集、UI 动效、动态排版 / 卡点、Logo 演绎、片头、循环动图 | ✅ |
| 视频模型生成的绿幕人物 + 代码做的场景、大字、动效 | ✅ 人物由用户提供（`references/formats.md` H 类） |
| 有口播稿或文章、要逐句讲解的几分钟视频 | ❌ 用 `web-video-presentation` |
| 网页、落地页、交互原型、静态视觉稿 | ❌ 用 `web-design-engineer` |
| 写实人物表演、实拍质感、剪辑已有素材、用视频模型直接出画面 | ❌ |

**时长**：最适合 5–60 秒。纯音乐驱动、没有旁白的片子可以做到 2 分钟左右（比如 `mixed-media-era` 那种年代回顾）；超过 60 秒时按段落分别制作、分别检查，开工前跟用户说清楚渲染和审片的成本。需要旁白讲解的视频不在本 Skill 范围内。

## Opus 的长处和默认坑

- **长处**：一个文件里能混用 Canvas、SVG/DOM、WebGL、Three.js，甚至每段换一种媒介；运动可以用公式精确计算（闭式弹簧、节拍网格、子帧运动模糊）；声音和画面读同一张时间表；能长时间自主「渲静帧 → 看图 → 修改」；审美判断力强，一句「全力以赴」就可能出很惊艳的东西。
- **默认坑**：没有约束时，画面会落到深色背景、居中大字、所有元素一起淡入、紫蓝渐变加发光、机位不动；配乐会落到 A 小调四踩、每个重拍 impact + crash、钟声落版，几支片子听起来像同一首歌。所以要先找对标（画面和声音都要）、写清风格和禁止清单。但约束也不能写死：这个 Skill 的风格库和手法库都是起点，主题需要时随时改造、混搭或自定义。
- **做不好的**：写实人物、复杂的手部 / 布料 / 毛发、需要真实物理精度的东西、照片级产品（除非用户提供模型或图片）。遇到这些就风格化处理，或者换成绿幕人物 + 代码场景的分工。

---

## 工作流

```
0 环境检查（一次）
1 一次问清 ──────── 能从请求里推断的就不问
2 brief.md ──────── 对标 → 用途 + 风格 → Reel Read → 节拍网格 + 分镜 + 禁止清单
3 风格帧 ────────── 🛑 唯一的停顿点：已定风格 → 1 个方向 3 张帧；未定风格 → 3 个方向各 1 张帧
4 制作 ──────────── timeline → 逐镜头 → 静帧自检 → 确定性检查 → 小样 → 正片
5 声音（可选）────── 代码合成 / 用户曲子 / 无声
6 验收 ──────────── 技术检查（程序判定，必须全过）+ 审片（看图列问题，交给用户终审）
7 交付
```

工作目录：在用户当前目录下建 `<slug>/`，所有文件都放在里面：`brief.md`、`index.html`、`motion.js`、`timeline.js`、`score.mjs` 或 `score.tone.js`（按 scaffold 的 `--audio` 选择）、`build.sh`、`fonts/`、`assets/`、`audio/`、`qa/`、`out/`。

### 第 0 步：环境

第一次使用时运行 `sh <skill>/scripts/setup.sh`：它会安装 Playwright 和 Chromium，再跑 `check-env.mjs`。需要 Node 18+ 和 ffmpeg；缺了就告诉用户怎么装，不要替用户装系统软件。工具自带测试：`cd <skill>/scripts && npm test`。

### 第 1 步：一次问清

**用一条消息**问，最多 5 个问题，请求里已经回答过的就跳过。用户说「你看着办」，就全部用默认值，并在 brief 里注明。

| 问什么 | 默认值 |
|---|---|
| 主题和素材：logo、产品截图、文案、品牌色、字体 | 只用用户给的事实，不编功能、数据和客户 |
| 观众看完要记住的一句话或一个画面 | 从主题里提炼 |
| 时长、画幅、平台 | 15 秒 · 1920×1080 · 30fps；竖屏平台用 1080×1920；UI 动效可以用 60fps |
| 风格：有指定的风格、参考视频或截图吗？ | 没有就在第 3 步给 3 个方向，看图选 |
| 声音：无声 / 代码合成 / 你提供曲子（需能商用） | 代码合成 |

- 用户给了参考视频：先跑 `inspect.mjs sheet <ref> --cells 30` 看全貌，`inspect.mjs grid <ref> --strips` 量出剪点和它们落的节拍网格（BPM 候选、每段占几步、每个转场的连续帧），`inspect.mjs heat <ref>` 看每段里哪里在动、动多大面积。把量到的数写进 brief 的对标一栏。只学结构和手法，不搬素材。
- 用户给了曲子：先跑 `audio.mjs beats <track> --out <slug>/audio/beats.json`。
- 画面里要出现的产品、品牌或技术名词，不确定的先查证。

**放手模式**：用户说「全力以赴」「你随意」「给我惊喜」，或者只给了一个主题、没有其他要求时，进入放手模式：只守底线和技术管线，风格、结构、手法都由你自己判断，可以完全不用风格库里的风格。仍然要写 brief（这是让你自己的创意可控、可复现的方式），仍然在第 3 步给 3 个方向。

### 第 2 步：brief.md

**先找对标**：动笔前为这支片子（这个主题 + 这种用途）挑 1–2 个对标作品，可以是电影片头、广告、游戏、动效作品、设计流派。在 brief 里写下「学什么」（构图、节奏、镜头语法、配色逻辑、配乐结构）和「不学什么」（角色、具体镜头、旋律、logo、字体文件）。对标比任何规则都更能拉高上限。

**再想三个候选结构**：比如一段旅程、一次前后对比、一次倒数、一个变成另一个、一个不切镜头的长镜头。各用两三行写下来，选一个并写明理由。第一个冒出来的想法往往是这个风格的陈词滥调。

**用途**和**风格**分开选：
- 用途（拍什么、按什么结构讲）看 `references/formats.md`，只读对应的那一节。
- 风格（长什么样、怎么动、什么声音）先看 `references/styles/INDEX.md`，再**只读选中的 1–2 个风格文件**。风格可以直接用、改造（替换其中一两条规则）、混搭（一主一辅，或者按段落切换媒介），也可以按 `styles/_template.md` 自定义。风格规则保持不变，故事、镜头和结构从用户的主题来，不要沿用别的片子。每个风格文件都有「辨识信号」和「最俗的版本」两节：按主题挑 2–3 个信号（至少一个不在俗套里），在 brief 里写明翻掉了俗套的哪几条，或者为什么保留。用户选了风格，要的是一眼认出这个风格，两三个信号就够了。
- 再按需翻 `references/craft.md`（手法库）。

按 `references/brief-template.md` 写 brief，核心是：

```yaml
Reel Read:
  format: [用途，formats.md 里的类型]
  benchmark: [对标作品 · 学什么 · 不学什么]
  structure: [三个候选结构 → 选中哪个、为什么]
  style: [styles/ 里的风格（含改造点），或者混搭方案，或者自定义规则]
  signals: [挑了哪 2–3 个辨识信号、为什么；翻掉了俗套的哪几条]
  takeaway: [观众记住的一句话或一个画面]
  hook: [前 1 秒发生什么]
  signature: [记忆点：第几秒、什么手法]
  palette / type / motion / camera / texture: [按所选风格写出具体值]
  sound: [无声 / 合成（声音对标、律动、和声、配器、曲线，见 sound.md 第 2 节）/ 用户曲子（BPM、drop）]
  forbidden: [这支片子的禁止清单]
```

接着在 brief 里写**节拍网格 + 分镜表**：先定 BPM 和小节数，每个镜头一行，写明 `拍号区间 | 画面（含原文文字）| 运动 | 镜头 | 声音 | 转场`。

用户只说了一句「全力以赴」，也要把它翻译成上面这份具体约束，否则结果就是抽卡。

### 第 3 步：风格帧（🛑 唯一停顿点）

建项目：`sh <skill>/scripts/scaffold.sh <slug> [--audio synth|tone|layer|none]`（默认 synth = 第 1 档合成；只拷贝选中的那份 score，`build.sh` 的 `AUDIO=` 也随之设好）。starter 只用来验证管线能跑通，画面和文案都要换掉。先写 `timeline.js`。

**A. 用户已经定了风格**（或者给了明确的参考）：
1. 用真代码搭出 hook 帧、记忆点帧、结尾帧，配色、字体、文案都用最终的。
2. `render.mjs <slug> --still 0.6,7.2,14.5 --sheet`，自己先看一遍，明显的问题修完再给用户。记忆点靠运动的话，另出一段 2–3 秒的小样（`--start --duration`）。
3. 把 Reel Read 摘要、分镜概要、风格帧发给用户，问「方向对吗？」。

**B. 用户没定风格（包括放手模式）**：给 **3 个拉开差距的方向**，规则见 `styles/INDEX.md`：
- A 贴合主题 / 品牌，B 换一种画面语言（来自另一个分组），C 大胆（自定义、混搭或结构上很大胆，至少一个方向不是库里现成的）。
- 每个方向写一段迷你 Reel Read（风格、对标、记忆点、配乐方向，3–5 行），并用真代码渲**一张**最能代表它的关键帧。三个方向的页面放在同一个项目里，用 `?dir=a|b|c` 切换。B、C 只为这一张关键帧服务，不必做成能播的整片。
- `render.mjs <slug> --directions a,b,c --at 14.5,2,0` 一次渲出三张并拼成带标签的 `qa/directions.png`，发给用户，问「选哪个，或者怎么混合？」。

两种情况都**真的等用户回复**，再进入制作。用户事先说过不用确认的，就自己选一个、写明理由，自查后继续；交付时把没选的方向一起给用户（B 情况附上 `qa/directions.png`，A 情况各写一句另外两个可能的方向），让用户回来还能换。

### 第 4 步：制作

制作前先读 `references/stack.md`（页面契约、确定性、各技术的坑）。要现成写法时查 `references/recipes.md`。

1. 时间点全部写进 `timeline.js`，页面和 `score.mjs` 都从这里 import。镜头表写进 `SHOTS`（验收时按镜头报运动），刻意的停留写进 `HOLDS`（比如落版 `[[b(36), DUR]]`），要留呼吸的重拍写进 `DROPS`，验收工具会读它们。转场要对拍时，用 `revealOn(拍点, 转场时长, 揭开点)` 倒推起点，让新画面露出来的那一帧落在拍上。
2. 逐个镜头做。每个镜头渲开头、中段、结尾 3 张静帧；快速动作用 `inspect.mjs strip` 看连续帧。
3. 跑确定性检查 `render.mjs <slug> --determinism`，不通过就先修。
4. 片长 30 秒以上或渲染慢的，先出低清小样：`--size 960x540 --out out/proxy.mp4`。
5. 出正片：先在 `build.sh` 顶部按 brief 设好 `FPS`、`SIZE`、`AUDIO`、`LOOP`，再 `sh <slug>/build.sh`。它会构建配乐，先跑确定性检查（不过不出片），再渲染，接着跑文字框景检查（只出审片材料，不挡构建），最后带着同一份规格跑技术检查（时长取 `timeline.js` 的 `DUR`）。`--subframes`、`--dpr`、`--grain` 作为参数加在后面，按风格需要加。这些参数都会成倍增加耗时，开渲前先报预计时间。

**硬规则**：
- 画面只由 t 决定：不用 `Math.random`、`Date.now`、rAF、定时器、CSS 动画，帧和帧之间不保存状态。
- 字体和素材全部加载完，再设置 `READY = true`；字体放进项目自托管。
- 布局从 `stageSize()` 返回的宽高推导，不写死像素。

### 第 5 步：声音（可选）

看 `references/sound.md`。声音方向（对标、律动、和声、配器、曲线）在第 2 步的 brief 里就定好，这一步按它来写；按风格选一档：

| 档 | 用什么 | 适合 |
|---|---|---|
| 第 1 档 · 内置合成 | `score.mjs`，Node 里的合成器（鼓、手鼓、贝斯、铺底、拨弦、马林巴 / 钢片 / 卡林巴、风琴、人声铺底、FM、环境底噪、音效、侧链、混响、lo-fi 处理），零依赖 | 电子、UI、芯片音乐、氛围、lo-fi、手作与玩具、大多数动效片 |
| 第 2 档 · Tone.js | `score.tone.js`，在无头浏览器里用 Tone.js 离线渲染：采样乐器（`audio.mjs samples salamander` 下载 CC BY 钢琴）、卷积混响、更丰富的合成器和效果 | 需要真实乐器、空间感、电影感的风格 |
| 外部曲子 | 用户提供的音乐（自己的、授权的、AI 音乐服务生成的） | 用户已有配乐 |

- 构建：`audio.mjs build <slug>/score.mjs` 或 `score.tone.js`，都会输出 −14 LUFS 的 `audio/music.wav`。
- 用户曲子：先跑 `audio.mjs beats`（有 librosa 时自动使用），对齐 timeline，再在 score 里 `S.load()` 进来叠音效。
- 无声：跳过这一步。

你听不到声音，所以每次 build 之后都要跑 `audio.mjs check`，看数值和图。`timeline.js` 里写了 `DROPS` 时，它还会量出每个重拍前那半拍的凹陷和重拍的抬升，没有呼吸就给 WARN。

### 第 6 步：验收

**技术检查**：由程序判定，失败就不能交付。

```bash
node <skill>/scripts/inspect.mjs qa <slug>/out/final.mp4 --out <slug>/qa/final \
  --expect-size 1920x1080 --expect-fps 30 --expect-duration 16 --audio required   # 无声片用 --audio none；循环片加 --loop
```

它检查文件能否解码、尺寸、帧率、时长、帧数、音轨、黑帧、响度、真峰值，以及循环接缝（需要时）。只要有一项 FAIL，退出码就是 1，必须修好。没传的规格项会列成 `NOT CHECKED`，这时不算验收通过。`build.sh` 会自动带上规格。渲染工具本身也会拒绝发布帧数不对的文件。

**审片**：给人判断用，不是程序判定。看抽帧图、手机尺寸抽帧图、冻结段（`HOLDS` 里声明过的会标成刻意停留，其余要判断是不是空拍）、切点、按镜头的运动和闪帧、文字框景的标记图（`qa/text-*.png`）、音频图，按 `references/review.md` 的审片表逐项写下观察和最严重的 3 个问题，有数字和图表的片子要核对内容与数字口径。修完只重渲有问题的那一段，再出整片，过程记到 `qa/review_log.md`。宿主支持子 agent 时，再派一个没参与制作的 agent 只看这些材料挑问题（review.md「独立审片」）。

审片结论是给用户的参考，**不能代替用户自己看片**。不适用的项标「不适用」，比如无声作品的音画同步，不要硬给分数。

### 第 7 步：交付

告诉用户：
- `out/final.mp4` 和 `out/poster.png` 的路径（poster：`render.mjs <slug> --poster <t>`）。
- `brief.md`：完整的结构化提示词，可以复用。
- 技术检查结果（全部 PASS）、审片记录里还没解决的问题、渲染用时。
- 怎么重建（`sh build.sh`）、怎么只改一段。
- 第三方素材（字体、用户素材、曲子）的来源和授权；事实类内容提醒用户再核对一遍。

交付之后花几分钟回看：哪一招明显让片子变好了，有证据（数字、前后对比）就记进 `references/field-notes.md`；用到的风格在 `styles/INDEX.md` 的「实做记录」里加一笔，新发现的短板写进那个风格文件的「坑」。只记可复用的方法，用户的素材和私人信息留在项目里。

---

## 底线（所有风格都要守）

1. **事实准确**：产品功能、数字、名称只来自用户或可靠来源，不确定的标出来。
2. **文字可读**：字号在手机尺寸下看得清，停留时间够读完（见 craft.md 第 7 节）；文字不溢出、不重叠、不被遮挡。
3. **素材有授权**：logo、截图、字体、曲子都要能用，并在交付时列出来。
4. **技术正确**：确定性渲染，技术检查全部通过，没有黑帧，结尾不能戛然而止（落版定格或无缝循环）。
5. **风格一致**：选定的风格规则从头守到尾，不落入 brief 的禁止清单。

除此之外，镜头动多少、用不用弹簧、音效密度、节奏快慢，都按风格和内容来定（见 references/styles/ 和 craft.md）。

---

## 工具速查（`S=<skill>/scripts`）

| 目的 | 命令 |
|---|---|
| 装依赖 / 查环境 / 自测 | `sh $S/setup.sh` · `node $S/check-env.mjs` · `cd $S && npm test` |
| 建项目 | `sh $S/scaffold.sh <slug> [--audio synth\|tone\|layer\|none]` |
| 静帧 + 拼图 | `node $S/render.mjs <slug> --still 0.5,3,7.2 --sheet` · `--range 0:15:1 --sheet` |
| 三个方向 / 封面 | `node $S/render.mjs <slug> --directions a,b,c --at 14.5,2,0` → `qa/directions.png` · `--poster 14.5` → `out/poster.png` |
| 确定性 | `node $S/render.mjs <slug> --determinism` |
| 文字框景（审片材料） | `node $S/render.mjs <slug> --text-check [--safe auto\|none\|T,R,B,L]` → `qa/text.json` + 标记图（build.sh 自动跑） |
| 拆参考片 | `node $S/inspect.mjs grid <ref> --strips`（剪点 + 节拍网格 + 转场连续帧）· `heat <ref>`（每段的运动热图） |
| 小样 / 正片 / 分段 | `--size 960x540 --out out/proxy.mp4` · 正片 `sh <slug>/build.sh --subframes 2 --grain 4`（规格在 build.sh 顶部）· `--start 6 --duration 3 --out out/seg.mp4` |
| 声音 | `node $S/audio.mjs build <slug>/score.mjs`（或 `score.tone.js`）· `samples salamander` · `beats <track> --out audio/beats.json` · `check audio/music.wav`（读 `DROPS`） |
| 验收与审片材料 | `node $S/inspect.mjs qa out/final.mp4 --expect-…`（build.sh 自动带）· `sheet` · `phone` · `strip --at 4.2` · `loop` · `motion`（读 `SHOTS` / `HOLDS`：按镜头的运动、跳变、闪帧） |

## 参考文件（按需读）

| 文件 | 什么时候读 |
|---|---|
| `references/formats.md` | 第 2 步：用途，比如宣传短片、作品集、UI 动效、排版卡点、Logo、数据爆点、绿幕合成 |
| `references/styles/INDEX.md` | 第 2 步：28 种风格的目录、三方向规则、混搭规则；然后只读选中的 `styles/<slug>.md`。自定义用 `styles/_template.md` |
| `references/craft.md` | 第 2 和第 4 步：节奏、运动、转场、镜头、排版、配色、质感、记忆点、默认味清单 |
| `references/brief-template.md` | 写 brief 时 |
| `references/stack.md` | 第 4 步：页面契约、确定性、各技术的坑、字体、素材、多画幅、性能 |
| `references/recipes.md` | 要现成写法时 |
| `references/sound.md` | 第 2 步（第 2 节：声音方向）和第 5 步 |
| `references/review.md` | 第 6 步：技术检查说明、审片表、独立审片、常见问题、交付清单 |
| `references/field-notes.md` | 第 2 步想参考前人做法时；第 7 步交付后回写 |
