免费

动效素材库

46 种剪纸定格动效:把脚本的每个段落对应到一种效果,填好一个 JSON,直接渲染 1080p 短片。

安装

把“动效素材库”技能安装到 ~/.claude/skills/motion-beats。
下载下面每个文件,保存到这个文件夹:
https://skilllift.pages.dev/packs/motion-beats/SKILL.zh.md → SKILL.md
https://skilllift.pages.dev/packs/motion-beats/references/style.md → references/style.md
https://skilllift.pages.dev/packs/motion-beats/assets/engine.html → assets/engine.html
https://skilllift.pages.dev/packs/motion-beats/assets/engine.js → assets/engine.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-title-behind.js → assets/fx-title-behind.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-chart-scan.js → assets/fx-chart-scan.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-one-look-stack.js → assets/fx-one-look-stack.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-corner-drag.js → assets/fx-corner-drag.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-screen-wall.js → assets/fx-screen-wall.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-topic-cloud.js → assets/fx-topic-cloud.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-card-row.js → assets/fx-card-row.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-chat-stack.js → assets/fx-chat-stack.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-status-focus.js → assets/fx-status-focus.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-light-spectrum.js → assets/fx-light-spectrum.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-post-scan.js → assets/fx-post-scan.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-best-match.js → assets/fx-best-match.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-ink-crumble.js → assets/fx-ink-crumble.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-gallery-pan.js → assets/fx-gallery-pan.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-grading-lens.js → assets/fx-grading-lens.js
https://skilllift.pages.dev/packs/motion-beats/assets/fx-mascot-window.js → assets/fx-mascot-window.js
https://skilllift.pages.dev/packs/motion-beats/assets/catalogue.json → assets/catalogue.json
https://skilllift.pages.dev/packs/motion-beats/assets/library.json → assets/library.json
https://skilllift.pages.dev/packs/motion-beats/assets/library.zh.json → assets/library.zh.json
https://skilllift.pages.dev/packs/motion-beats/assets/sample-screen.png → assets/sample-screen.png
https://skilllift.pages.dev/packs/motion-beats/assets/sample-screen.zh.png → assets/sample-screen.zh.png
https://skilllift.pages.dev/packs/motion-beats/scripts/render.mjs → scripts/render.mjs
https://skilllift.pages.dev/packs/motion-beats/scripts/check.mjs → scripts/check.mjs
https://skilllift.pages.dev/packs/motion-beats/scripts/sheet.mjs → scripts/sheet.mjs
https://skilllift.pages.dev/packs/motion-beats/scripts/shared.mjs → scripts/shared.mjs
https://skilllift.pages.dev/packs/motion-beats/scripts/cutout.mjs → scripts/cutout.mjs
https://skilllift.pages.dev/packs/motion-beats/scripts/segment-person.swift → scripts/segment-person.swift
然后读一遍 SKILL.md,告诉我它是做什么的,并提醒我开一个新会话。

解压到 ~/.claude/skills

同一个技能,不同的需求

左边是预览。右边由另一个 Agent 按不同需求制作,它只有安装好的技能,没看过预览。

预览
预览
新需求,由另一个 Agent 制作
新需求,由另一个 Agent 制作

这是按虚构需求做的一次测试。系统字体不同时,字形可能略有差异。

动效素材库:46 种短动效片段,给创作者和产品团队用,全部是同一引擎驱动的剪纸定格风格。给一份脚本、提纲或产品事实,它把每个关键段落对应到一种效果,填好文字,渲染成 1920x1080、30 fps、H.264 的 4 到 8 秒 MP4,也可以再拼成一条完整短片。需要讲解片段、数据动效、章节卡、动态文字、引用卡或片尾卡,又没有实拍、配音和音乐时使用。支持中文和英文。

交付前必须通过

  • 对文件夹运行 check.mjs 退出码为 0,引用它的最后一行。
  • 每段的效果都符合这一段在做的事,没有合适效果的地方用了中性效果。
  • 看过每个最终 MP4 抽出的真实画面,不只是拼图。
  • 比较看得出在比,增长看得出在长,每个意思一眼能懂,想让人记住的那句足够大。
  • 每个 callout-panel 都用了真实图片,圆环都落在所指的内容上。
  • 屏幕上每个数字都在用户原文里,推断内容已经列出。
  • 一个版本一种语言,一条短片一种配色。
  • 没有生成实拍、配音或音乐。
  • 虚构内容已通过 label 标明。
阅读完整 SKILL.md
---
name: motion-beats
description: 动效素材库:46 种短动效片段,给创作者和产品团队用,全部是同一引擎驱动的剪纸定格风格。给一份脚本、提纲或产品事实,它把每个关键段落对应到一种效果,填好文字,渲染成 1920x1080、30 fps、H.264 的 4 到 8 秒 MP4,也可以再拼成一条完整短片。需要讲解片段、数据动效、章节卡、动态文字、引用卡或片尾卡,又没有实拍、配音和音乐时使用。支持中文和英文。
version: 1.0.0
---

# 动效素材库

所有文字和数值都在一个 JSON 文件里,改完一条命令重新渲染。样式写死在 `assets/engine.html` 和 `assets/engine.js`:你负责选效果、写内容,不要改样式。精确的颜色、字号和时序见 `references/style.md`。

## 先问清楚

简报里没有的,一次问完:

1. 脚本、提纲或产品事实。原样放进 `"source"`。
2. 语言:`zh` 或 `en`。一个版本只用一种语言,两种都要就做两个 JSON。
3. 只要片段,还是也要拼一条完整短片。
4. 配色:`vermilion`(朱红)、`cobalt`(钴蓝)、`pine`(松绿)、`apricot`(杏色)。没人指定时,发布类用 `vermilion`,产品和数据用 `cobalt`,理财或平和的话题用 `pine`,个人故事用 `apricot`。
5. 用 `callout-panel` 时要真实截图;没有就换效果。

**没人回答时:** 继续做,把假设列在回复最前面。

## 步骤

1. 把内容拆成关键段落:一段一个意思,一个片段,大约每 5 秒脚本一个片段。先想清楚这一段**在做什么**。
2. 在下表里选 `job`,再选这个 job 下第一个能用原始内容真实填满的效果,并参考“怎么选得好”。**没有合适的效果时,用中性效果 `phrase-emphasis`,job 填 `statement`。** 它适用于任何一句话。
3. 新建文件夹写 `beats.json`,比如 `motion/beats.json`。`assets/library.zh.json` 和 `assets/library.json` 里有每种效果填好的合法示例,抄结构,不要抄里面虚构的文字。
4. 校验:`node <skill>/scripts/check.mjs motion/beats.json`,报什么改什么。
5. 渲染前先看:`node <skill>/scripts/sheet.mjs motion/beats.json motion/sheet.png` 会把每段的最后一帧拼成一张图,用看图工具打开。哪段一眼看不懂,就换效果或把字改短。
6. 渲染:`node <skill>/scripts/render.mjs motion/beats.json --out motion`。要完整短片加 `--film`。
7. 检查观众实际看到的:`node <skill>/scripts/check.mjs motion`。改 JSON,用 `--only b03` 只重渲改过的片段,再查,直到通过。
8. 从最终 MP4 抽帧,每个片段都要看:`nice -n 10 ffmpeg -threads 2 -ss 2 -i motion/clips/b03.mp4 -frames:v 1 b03.png`。效果有没有把意思表达出来,检查脚本判断不了,只能你看。

常用渲染选项:

- `--only b03,b07`:只渲染这几段。
- `--only b03 --frame 120`:只重渲一帧,存到 `motion/frames/b03-120.png`,约一秒。
- `--stills 0.3,0.6,1`:每段按这些时间点各出一张静帧。
- `--scale 0.5`:半尺寸草稿,存到 `motion/draft/`,迭代时用。检查脚本不接受草稿。
- `--film-only`:把现成片段拼成短片。
- `--flat`:输出到 `motion/<id>.mp4`,而不是 `motion/clips/<id>.mp4`。
- `--crf 24`:设定短片压缩率。短片会自动加大压缩,直到小于 `film.maxMB`。

这台机器上渲染很吃资源:迭代时用小尺寸,准备好了才出完整 MP4,不要同时跑两个渲染,也不要用按进程名批量结束进程的命令。渲染脚本已经是低优先级、单浏览器、ffmpeg 两线程。

**检查选项。** `check.mjs` 可以在技能安装的位置独立运行,参数可以是 JSON、文件夹或任意 MP4。文件夹会对照里面的 `beats.json` 检查,也可以用 `--beats path/to/beats.json` 指定;片段可以放在 `clips/<id>.mp4`,也可以平铺成 `<id>.mp4`。文件夹里对不上段落的 MP4 会给出警告。`check.mjs clip.mp4 --beats beats.json` 核对单个片段和 JSON。`--quick` 抽帧更少。`check.mjs --test` 是短自检,约 2 秒,证明它确实能查出静止片段、错误效果名、编造数字等问题。遇到不是本技能生成的 MP4,它仍会检查格式、静止、空白和整体对比度,并提示文字检查已跳过,不会报错退出。

## beats.json

```json
{
  "lang": "zh",
  "palette": "cobalt",
  "label": "虚构示例",
  "source": "用户的原文,不做改动",
  "film": { "maxMB": 10 },
  "beats": [
    { "id": "b01", "job": "growth", "effect": "bars-grow", "seconds": 6,
      "slots": { "title": "每季度注册人数", "bars": [ {"label":"一季度","value":120}, {"label":"二季度","value":310} ] } }
  ]
}
```

| 字段 | 含义 | 上限 | 简报单薄时 |
|---|---|---|---|
| `lang` | 屏幕上所有文字的语言 | `zh` 或 `en` | 跟原文语言一致 |
| `palette` | 唯一的配色设置 | 四选一 | 见“先问清楚”第 4 条 |
| `label` | 每个片段上的小标签 | 30 字以内,可选 | 示例内容才用,比如“虚构示例”;真实项目省略 |
| `source` | 用户原文,不做改动。屏幕上每个数字都必须能在这里找到 | 必填 | 给什么贴什么,再短也贴 |
| `keepLatin` | 中文版里允许保留拉丁字母的真实名称 | 列表,可选 | 省略,或只列真实名称 |
| `film.transition` | 整条短片统一的衔接;省略时在 blade、slats、iris 之间轮换 | `wipe-blade`、`wipe-slats`、`wipe-iris`、`cut` | 省略 |
| `film.maxMB` | 短片大小上限 | 数字,默认 10 | 省略 |
| `beats[].id` | 片段文件名 | 字母、数字、连字符 | b01、b02 依次编号 |
| `beats[].job` | 这一段在做什么 | 见下表 | `statement` |
| `beats[].effect` | 效果名 | 目录里的准确名称 | `phrase-emphasis` |
| `beats[].seconds` | 片段时长 | 4 到 8 | 填 6。字很少的卡片才用 4 或 5,内容多的用 7 或 8 |
| `beats[].transition` | 这段之后的衔接 | 同 `film.transition`,可选 | 省略 |
| `beats[].slots` | 效果的字段 | 见下文 | 见下文 |

## 怎么选效果

| 这一段在做什么 | `job` | 可选效果(首选在前) |
|---|---|---|
| 比较两样东西 | `compare` | `compare-columns`, `before-after`, `strike-swap`, `bars-grow`, `unit-grid`, `chart-scan`, `best-match`, `grading-lens` |
| 展示增长 | `growth` | `bars-grow`, `line-rise`, `stair-steps`, `number-counter`, `chart-scan`, `light-spectrum` |
| 把各项加成合计 | `total` | `ledger-total` |
| 部分占整体 | `share` | `ratio-ring`, `gauge-dial`, `unit-grid` |
| 标明章节 | `chapter` | `title-stamp`, `chapter-number`, `label-reveal`, `shutter-title`, `title-behind` |
| 强调一句话或一个数字 | `stress` | `phrase-emphasis`, `word-stack`, `strike-swap`, `typed-answer`, `number-counter`, `title-behind`, `topic-cloud`, `chat-stack`, `ink-crumble` |
| 讲解步骤或流程 | `steps` | `flow-nodes`, `stair-steps`, `cycle-loop`, `layer-stack`, `branch-tree`, `status-focus` |
| 展示结构 | `structure` | `branch-tree`, `layer-stack` |
| 引用某人 | `quote` | `pull-quote`, `speaker-card`, `post-scan` |
| 介绍讲者 | `intro` | `speaker-card` |
| 指出真实截图或图片的局部 | `show` | `callout-panel`, `one-look-stack`, `corner-drag`, `screen-wall`, `card-row`, `gallery-pan`, `grading-lens`, `mascot-window` |
| 以行动收尾 | `close` | `name-action`, `action-list`, `screen-wall`, `mascot-window` |
| 段落之间的过渡 | `transition` | `wipe-blade`, `wipe-slats`, `wipe-iris` |
| 其他:一句普通陈述 | `statement` | `phrase-emphasis`, `typed-answer`, `chat-stack`, `post-scan` |

## 怎么选得好

- **柱图还是折线。** 有 2 到 7 个数值、要让人比大小时用 `bars-grow`,几个月或几个季度也一样。`line-rise` 只用于连续时间上 4 个及以上的点,且重点是走势。
- **一句普通的好处**(比如“一屏看完所有班次”):能压缩成几个有力的词就用 `word-stack`,整句都重要就用 `phrase-emphasis`。有真实界面才用 `callout-panel`。
- **`callout-panel` 要用真东西。** 向用户要产品的真实截图或图片,写成 `{"src":"file.png"}`。没有界面就换别的效果。绝不能用线框冒充产品;除非这一段泛泛讲版面并写明 `"abstract":true`,否则检查脚本会拒绝。每个标注都要指向真实存在的内容:看画面,调 `x` 和 `y`,直到圆环落在它上面。
- **前后不对等**(“四个网站”对“一个应用”):这正是最好的情况。之后一侧只有一项时,它会撑满整侧成为点睛之笔,所以字要少。
- **点睛的词要撑满画面。** 字越少越大。想让人记住的那句,用只有 key 的 `phrase-emphasis` 或 `word-stack`。
- **重复。** 同一效果连用两次像是失误,检查脚本会警告。隔开再用没问题。
- 比较就要让人看到在比,增长就要让人看到在长。原始内容有两边或有数字时,不要只用文字效果。

## 短片里的色彩和尺度变化

这一项没有设置。每段都落在所选配色的四种底色之一:`field`、`night`、`paper`、`accent`。底色由 job 决定,并且不与上一段相同,所以整条短片的颜色会流动:强调和收尾用 accent,图表和引用用 night,比较用 paper。底色取决于段落顺序,调整顺序后颜色会变,需要重新渲染。片段单独看和在短片里看是一样的。每个片段还有缓慢的推镜,每次撞击再推一下。衔接为 14 帧,前面带亮、暗两道边;不写 `film.transition` 时,会在 blade、slats、iris 之间轮换。

## 效果目录:共 46 种

**数据**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `bars-grow` | 纸条柱从零依次升起,数值同步滚动,重点柱落在强调色上。 | `title`? ≤22; `prefix`? ≤2; `suffix`? ≤4; `count`?: true/false; `highlight`?: 数字; `bars` [2–7] {label ≤8, value: 数字} |
| `line-rise` | 粗线沿各点向上爬升,刻度从零开始,线下填色,线头经过时数值弹出。 | `title`? ≤22; `prefix`? ≤2; `suffix`? ≤4; `points` [2–8] {label ≤6, value: 数字} |
| `ledger-total` | 撕边的小票逐行打出,每行飞出一枚小块落到合计,合计随之跳动。 | `title`? ≤22; `prefix`? ≤2; `suffix`? ≤4; `count`?: true/false; `totalLabel` ≤8; `rows` [2–6] {label ≤12, value: 数字} |
| `ratio-ring` | 多边切面的圆环扫到数值占满额的比例,中心数字同步滚动。 | `title`? ≤22; `value`: 数字; `max`: 数字; `prefix`? ≤2; `suffix`? ≤4; `count`?: true/false; `caption`? ≤36 |
| `gauge-dial` | 半圆刻度盘逐块填色,指针冲过数值再摆回落定。 | `title`? ≤22; `value`: 数字; `min`: 数字; `max`: 数字; `prefix`? ≤2; `suffix`? ≤4; `count`?: true/false; `caption`? ≤36 |
| `unit-grid` | 每格代表一个单位,方块逐个翻成强调色,直到数出“总数中的多少”。 | `title`? ≤22; `value`: 数字; `total`: 数字; `count`?: true/false; `caption`? ≤36 |

**图解**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `flow-nodes` | 纸板按折线落位,圆点沿箭头前进,依次点亮每个节点。 | `title`? ≤22; `steps` [3–5] {label ≤12} |
| `branch-tree` | 主干从根节点长出,分成枝,再分成叶。 | `title`? ≤22; `root` ≤10; `branches` [2–3] {label ≤10, leaves[] (0–3) ≤14} |
| `before-after` | 左边歪斜暗沉地落下,右边一块锯齿亮板砸入,内容排得整整齐齐。 | `title`? ≤22; `beforeLabel` ≤6; `afterLabel` ≤6; `before` [1–3] {text ≤16}; `after` [1–3] {text ≤16} |
| `cycle-loop` | 箭头连成闭环,圆点不停绕行,经过哪块纸板哪块就跳一下。 | `title`? ≤22; `center`? ≤8; `stages` [3–6] {label ≤8} |
| `layer-stack` | 斜切的板从底层起逐块落下,砸在堆上,每层标签沿引线拉出。 | `title`? ≤22; `layers` [3–5] {label ≤12, note ≤20?} |
| `stair-steps` | 纸柱搭起台阶,一枚记号一级一级跳到顶。 | `title`? ≤22; `steps` [3–5] {label ≤10} |

**动态文字**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `word-stack` | 每个词撑满整行宽度,左右交替砸入,直到填满画面。 | `words` [2–5] {text ≤8} |
| `phrase-emphasis` | 一句话逐词升起,一块色纸冲到关键词下面并翻转颜色。这是通用的中性效果。 | `before`? ≤34; `key` ≤18; `after`? ≤34 |
| `typed-answer` | 问题纸板落下,答案在深色卡片上逐字打出,配粗光标。 | `question` ≤28; `answer` ≤50 |
| `number-counter` | 里程表式的数字块滚到给定数值,越靠右转得越多,下方标签条滑入。 | `value`: 数字; `prefix`? ≤2; `suffix`? ≤4; `count`?: true/false; `label` ≤20; `caption`? ≤36 |
| `strike-swap` | 错误说法被一刀划掉并撞开,正确说法落在亮色纸板上。 | `lead`? ≤20; `wrong` ≤14; `right` ≤14 |

**章节卡**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `title-stamp` | 带框标题从上方盖下,撞击让画面一震,纸屑飞溅。 | `title` ≤14; `sub`? ≤30 |
| `chapter-number` | 巨大的章节号分成上下两半滑入并咬合,随后标题跟上。 | `number` ≤2; `title` ≤14; `sub`? ≤30 |
| `label-reveal` | 三条长纸带依次掠过画面,最后一条把标签拖出来。 | `label` ≤14; `sub`? ≤26 |
| `shutter-title` | 深色竖条按波浪依次收拢,露出纸色底上的标题。 | `title` ≤14; `sub`? ≤30 |

**讲者与引用**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `pull-quote` | 巨大的剪纸引号翻滚落下,文字依次升起,署名条滑入。 | `quote` ≤56; `who` ≤14; `role`? ≤20 |
| `compare-columns` | 一行行从两侧滑向中线。若有胜者,该列升起并染上强调色,另一列下沉。 | `title`? ≤22; `leftName` ≤8; `rightName` ≤8; `winner`?: left/right; `rows` [2–5] {a ≤14, b ≤14} |
| `callout-panel` | 真实截图贴在纸板上滑入,标注旗连着引线飞到准确位置的圆环上。 | `title`? ≤22; `panel`: 对象; `callouts` [1–4] {text ≤12, x: 数字, y: 数字} |
| `speaker-card` | 剪纸话筒不断发出声波弧,名字砸入,职务条和要点随后跟上。 | `name` ≤10; `role`? ≤20; `points`? [0–3] {text ≤20} |

**收尾与转场**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `name-action` | 名字大字落下,剪纸箭头飞来反复按动行动按钮,每按一次阴影塌下。 | `name` ≤12; `action` ≤16; `url`? ≤40 |
| `action-list` | 方框排成一列,剪纸对勾依次砸进去。 | `title`? ≤22; `actions` [1–3] {text ≤20} |
| `wipe-blade` | 带亮边的锯齿刀口横切画面,把上一个词换成下一个词。也用于成片的衔接。 | `from` ≤10; `to` ≤10 |
| `wipe-slats` | 竖条按波浪合上,露出下一个画面。也用于成片的衔接。 | `from` ≤10; `to` ≤10 |
| `wipe-iris` | 多边切面的圆从画面中心长大,直到吞没整个画面。也用于成片的衔接。 | `from` ≤10; `to` ≤10 |

**展示段落(更长,可放图片)**

| 效果 | 画面 | 字段(≤字数,? 为可选) |
|---|---|---|
| `title-behind` | 人物剪影落下,巨大标题从头后冲出并铺满画面,脸始终不被挡住。 | `title` ≤12; `sub`? ≤30; `person`?: 透明人物 PNG |
| `chart-scan` | 讲者栏固定在大柱图旁。镜头从行名沿柱子走到端点,在每个数字上停顿,再转到下一组,最后拉回看全图。 | `title`? ≤22; `speaker`? ≤8; `role`? ≤12; `person`?: 透明人物 PNG; `prefix`? ≤2; `suffix`? ≤4; `groups` [1–4] {label ≤10, rows[] (0–5) ≤8} |
| `one-look-stack` | 全屏图片收成卡片,更多卡片落成扇形一叠,三张依次弹出,最后全部排成打勾的几行,铺满画面。 | `headline` ≤16; `sub`? ≤30; `pop1`? ≤10; `pop2`? ≤10; `pop3`? ≤10; `rowTitle`? ≤20; `action`? ≤12; `pictures`?: 图片 ≤11 |
| `corner-drag` | 手柄拖圆卡片的角,读数数到设计值;镜头拉回到发布卡,卡片落在 3x3 功能格中央,光标点下按钮。 | `name` ≤12; `feature`? ≤16; `button` ≤6; `readoutLabel` ≤12; `radius`: 数字; `unit`? ≤2; `features`? [0–8] {text ≤12}; `pictures`?: 图片 ≤9 |
| `screen-wall` | 播放器切到可点广告,镜头拉回 3x3 宫格,再炸开成 80 块屏幕的墙,品牌砸下,配标语和行动按钮。 | `show`? ≤14; `adText` ≤14; `adButton` ≤8; `brand` ≤6; `tagline`? ≤20; `cta`? ≤10; `pictures`?: 图片 ≤80 |
| `topic-cloud` | 短短的话题词飘进人物身后的云,然后其中一个来到前面的大纸板上。脸始终不被挡住。 | `topics` [3–12] {text ≤8}; `focus`?: 数字; `line`? ≤24; `person`?: 透明人物 PNG |
| `card-row` | 人物站在中景,一排卡片从前景升起,依次高亮,绝不挡脸。 | `title`? ≤22; `cards` [2–5] {title ≤10, note ≤18?}; `highlight`?: 数字; `person`?: 透明人物 PNG; `pictures`?: 图片 ≤5 |
| `chat-stack` | 普通的剪纸对话气泡逐条到来叠起,最后一条撑满画面,变成点睛的话。 | `messages` [2–6] {text ≤28, side?: left/right}; `payoff` ≤28 |
| `status-focus` | 侧栏里的状态逐项盖上相应的标记,然后镜头放大到其中一项,可配一句详情。 | `title`? ≤22; `items` [3–7] {label ≤12, state ≤6?, status?: good/delayed/cancelled/unknown}; `focus`?: 数字; `detail`? ≤36 |
| `light-spectrum` | 起始数字占满画面,一道光把纸板扫成色阶,结束数字接管画面,起始数字缩到一旁。 | `title`? ≤22; `start`: 数字; `end`: 数字; `prefix`? ≤2; `suffix`? ≤4; `label`? ≤20; `count`?: true/false |
| `post-scan` | 一张原创的普通帖子样张被逐行扫描,关键短语被标出,最后落在一句总结上。 | `author`? ≤12; `lines` [2–6] {text ≤28, mark ≤14?}; `summary` ≤32 |
| `best-match` | 产品卡片洗牌,按给定数值以真实比例打分,最高的一张升起成为最佳匹配。 | `title`? ≤22; `items` [2–5] {name ≤8, score: 数字}; `prefix`? ≤2; `suffix`? ≤4; `scoreLabel`? ≤10; `matchLabel`? ≤8; `pictures`?: 图片 ≤5 |
| `ink-crumble` | 扫描在卡片上标出细节,随后卡片和文字碎成纸屑和墨点,一句点睛的话逐字打出。 | `cardTitle` ≤14; `cardLines` [1–4] {text ≤20}; `flags`? [0–3] {text ≤10}; `payoff` ≤28 |
| `gallery-pan` | 镜头沿图片墙缓缓平移,每张图按顺序只出现一次,停留并显示说明,最后拉回看全墙。 | `title`? ≤22; `captions`? [0–8] {text ≤16}; `pictures`?: 图片 ≤8 |
| `grading-lens` | 圆形镜头滑过图片,镜内是调色后的版本,镜外是原样,然后撑满画面,配前后标签。 | `title`? ≤22; `beforeLabel`? ≤6; `afterLabel`? ≤6; `grade`?: natural/filmic/warm/cool/punch; `pictures`?: 图片 ≤1 |
| `mascot-window` | 页面上打开一扇窗,角色爬进来,挥手,伸长手臂指向标题,然后躲下去,窗板合上。 | `headline` ≤20; `sub`? ≤32; `action`? ≤12; `mascot`?: 透明人物 PNG |

`preview/catalogue.png` 有每种效果的真实画面。

## 每个字段

上限是中文字数,英文上限见 SKILL.md 和 `assets/catalogue.json`。上面带 ? 的字段可以整个省略,不要填占位文字。

| 字段 | 含义 | 上限(中文字数) | 简报单薄时 |
|---|---|---|---|
| `count` | 默认 true:数字滚动上升。false:屏幕上只出现最终给定的数字,没有过渡数字。简报要求只能出现给定数字时填 false。 | true/false | 省略;简报禁止出现其他数字时才填 false。 |
| `title` | 效果上方的标题,用脚本原话说明观众该得出什么。 | 12–22 | 省略。脚本没说的结论不要写。 |
| `sub` | 章节标题下的小字。 | 26–32 | 省略。 |
| `prefix` | 数字前的符号,如 ¥。 | 2 | 简报写明单位才填,否则省略。 |
| `suffix` | 数字后的单位,如 % 或 页。 | 4 | 简报写明单位才填,否则省略。 |
| `highlight` | 要着色的柱序号,或 card-row 里最后停留的卡片,从 0 开始。默认最大的柱子或最后一张卡片。 | 数字 | 省略。 |
| `bars.label` | 柱下名称。 | 8 | 用简报里的名称。没有名称就不用柱图,改用 phrase-emphasis。 |
| `bars.value` | 提供的数字,不小于 0。柱子从零起。 | 数字 | 不许估算。缺数值就改用 phrase-emphasis。 |
| `points.label` | 时间轴上的名称。 | 6 | 用简报里的日期或时段。没有就改用 phrase-emphasis。 |
| `points.value` | 该点提供的数字。 | 数字 | 不许插值或外推。少于两个值就改用 number-counter 或 phrase-emphasis。 |
| `totalLabel` | 合计旁的词,如“合计”。 | 8 | 填 Total;中文填“合计”。 |
| `rows.label` | 一行的名称。 | 12 | 用简报原话。 |
| `rows.value` | 提供的金额。引擎自己相加,合计是唯一计算出来的数。 | 数字 | 不许估算。缺金额就改用 phrase-emphasis。 |
| `value` | 提供的数字。 | 数字 | 不许估算。没有数字就改用 phrase-emphasis。 |
| `max` | 数值的满额;百分比就是 100。 | 数字 | 必须来自简报;简报给百分比时填 100,并把 suffix 设为 %。否则改用 number-counter。 |
| `min` | 刻度盘下限。 | 数字 | 用简报给的下限,或者 0(0 无需出处)。否则改用 number-counter。 |
| `total` | 方块总数,不超过 100 的整数。 | 数字 | 必须来自简报。否则改用 number-counter。 |
| `caption` | 解释这个数字的短句。 | 36 | 省略,不要猜数字的含义。 |
| `steps.label` | 一个步骤的名称,按顺序。 | 10–12 | 从脚本里取动词。不足三步就改用 before-after 或 phrase-emphasis。 |
| `root` | 分叉的那一个主题。 | 10 | 用脚本里这一段的主语。 |
| `branches.label` | 树的一根枝。 | 10 | 用脚本自己的分类。 |
| `leaves.label` | 枝下的一项。 | 14 | 脚本没提就省略。 |
| `beforeLabel` | 旧状态的名称。 | 6 | 填 Before;中文填“之前”。 |
| `afterLabel` | 新状态的名称。 | 6 | 填 After;中文填“之后”。 |
| `before.text` | 旧状态的一条事实。 | 16 | 转述脚本。脚本只说了一边就改用 phrase-emphasis。 |
| `after.text` | 新状态的一条事实。 | 16 | 转述脚本。脚本没说的成效不要写。 |
| `center` | 环中间的词。 | 8 | 省略。 |
| `stages.label` | 环上的一个阶段,按顺序。 | 8 | 脚本真的循环才用,否则改用 flow-nodes。 |
| `layers.label` | 一层的名称,从底层写起。 | 12 | 用脚本原话,按搭建顺序。 |
| `layers.note` | 该层的短注。 | 20 | 省略。 |
| `words.text` | 每行一个词或极短词组。 | 8 | 按顺序取脚本里最有力的词,不加新词。 |
| `before` | 关键词之前的文字。 | 34 | 关键词能独立成句就省略。 |
| `key` | 被色块衬底的短语,必填。 | 18 | 用脚本强调的词;不明确时取句末名词短语,并列入推断清单。 |
| `after` | 关键词之后的文字。 | 34 | 省略。 |
| `question` | 要回答的问题。 | 28 | 把这一段改写成它回答的问题,并列入推断清单。 |
| `answer` | 答案,用脚本原话。 | 50 | 用脚本原句,不加新说法。 |
| `label` | 数字统计的是什么,或章节标签。 | 14–20 | 用脚本的名词。含义不明就不用数据效果。 |
| `lead` | 错误说法上方的引子。 | 20 | 省略。 |
| `wrong` | 要被替换的说法。 | 14 | 必须出自脚本,不要虚构对立面。 |
| `right` | 替换后的说法。 | 14 | 必须出自脚本。 |
| `number` | 章节号,如 1、2、A。不要用“一”,在圆盘上像禁行标志。它是序号,不是数据。 | 2 | 按脚本顺序编号。 |
| `quote` | 原话,一字不改。只去掉属于引述句的标点,比如“某某说”前面的逗号。 | 56 | 只用用户提供的原话。没有就改用 phrase-emphasis,绝不代拟。 |
| `who` | 说话的人。 | 14 | 用简报里的名字。只是脚本本身的话,填 From the script;中文填“摘自脚本”。 |
| `role` | 原文写明的职务或身份。 | 12–20 | 原文写明才用,比如“测试用户”。否则省略,绝不虚构头衔。 |
| `leftName` | 左列名称。 | 8 | 用脚本对两边的称呼。 |
| `rightName` | 右列名称。 | 8 | 用脚本对两边的称呼。 |
| `winner` | left 或 right:脚本倾向的一边;中立比较就省略。 | left/right | 脚本没表态就省略。 |
| `rows.a` | 该行左格。 | 14 | 转述脚本。缺一边就不算比较,改用 phrase-emphasis。 |
| `rows.b` | 该行右格。 | 14 | 转述脚本。 |
| `panel` | 对象。用 {"src":"path.png"}:产品的真实截图或图片(PNG 或 JPG),路径相对 JSON。{"kind":"window","abstract":true}(也可以是 "phone"、"page")画不带文字的线框,不写 "abstract":true 检查脚本会拒绝。 | 对象 | 没有真实图片就不要用 callout-panel。普通的好处用 word-stack 或 phrase-emphasis,讲怎么用就用 flow-nodes。线框只用于泛泛讲版面的段落,绝不用来代表产品实际显示的内容。 |
| `callouts.text` | 这个位置是什么。 | 12 | 只写用户列出的功能。 |
| `callouts.x` | 在面板上的横向位置,0 到 1。是位置,不是数据。 | 0–1 | 线框图上分散摆放,0.25、0.75 都可以。 |
| `callouts.y` | 在面板上的纵向位置,0 到 1。是位置,不是数据。 | 0–1 | 线框图上 0.3、0.7 都可以。 |
| `name` | 人名、产品名或系列名。 | 10–12 | 用简报里的名字;没有就用脚本标题。 |
| `points.text` | 此人讲的一个话题。 | 20 | 省略。 |
| `action` | 观众下一步要做的一件事,用动词开头。 | 12–16 | 用脚本里的请求。name-action 没有请求时填 Find out more,中文填“了解更多”。one-look-stack 没有请求时省略,就不显示按钮。 |
| `url` | 要显示的真实地址。 | 40 | 没有真实链接就省略,绝不编地址。 |
| `actions.text` | 观众要做的一件事。 | 20 | 从脚本里取。只有一件就只写一件,或改用 name-action。 |
| `from` | 过渡片上一段的词。 | 10 | 用刚结束那一段的名字。 |
| `to` | 过渡片下一段的词。 | 10 | 用即将开始那一段的名字。 |
| `person` | 对象:{"src":"cutout.png"},人物的透明 PNG,路径相对 JSON。可加 "face":{"x":0.3,"y":0.1,"w":0.4,"h":0.25},都是相对图片的比例。 | PNG | 省略:会用一个明显通用的无脸剪纸人物。只有普通照片时,在 macOS 上运行 scripts/cutout.mjs。绝不生成写实人像。 |
| `pictures` | {"src":"file.png"} 的列表,PNG 或 JPG,路径相对 JSON。数量不够时会循环使用。 | 最多 80 张 | 省略:会用代码绘制、与配色一致的抽象图。用户有真实图片就用真实图片。 |
| `speaker` | 图表旁固定栏里的名字,可选。 | 8 | 简报没提到人就省略;同时没有 person 时,图表占满全宽。绝不虚构团队。 |
| `feature` | 这次发布要讲的新功能,大字显示在一条横带上,一直留到结尾。 | 16 | 用简报点名的功能。没有单一功能就省略。 |
| `groups.label` | 一组数据的名称。 | 10 | 用表格标题。只有一组也可以。 |
| `headline` | 卡片叠旁边的主句,最后移到几行卡片上方。 | 16–20 | 用脚本里最主要的一句话。 |
| `pop1` | 第一张弹出图片的说明。 | 10 | 省略:图片弹出时不带说明。 |
| `pop2` | 第二张的说明。 | 10 | 省略。 |
| `pop3` | 第三张的说明。 | 10 | 省略。 |
| `rowTitle` | 打勾的几行上方的文字。 | 20 | 省略。 |
| `button` | 发布卡上的按钮文字。 | 6 | 用简报里的行动,或者 Try it;中文填“试试看”。 |
| `readoutLabel` | 读数测量的是什么。要写明是设计值,比如“圆角(设计值)”。 | 12 | 填 Corner radius (design);中文填“圆角(设计值)”。 |
| `radius` | 读数数到的圆角值。这是用户设定的设计值,不是测量结果,也是这里唯一不需要出处的数字。绘制时按两倍显示,最大到卡片高度的一半,这样变化看得清。 | 数字 | 填 24。 |
| `unit` | 读数单位,默认“像素”。 | 2 | 省略。 |
| `features.text` | 卡片周围格子里的一项功能。 | 12 | 只写用户列出的功能;其他格子只放图片。 |
| `show` | 播放器上的标题。 | 14 | 省略。 |
| `adText` | 可点广告上的一句话。必填:广告为空时检查会失败。 | 14 | 转述简报里最主要的说法,并列入推断内容。 |
| `adButton` | 光标点的按钮。必填:按钮为空时检查会失败。 | 8 | 用简报里的行动。没有就填 Open,中文填“打开”,并列入推断内容。 |
| `brand` | 砸下来的品牌名。 | 6 | 用简报里的产品名。 |
| `tagline` | 品牌名下的一句话。 | 20 | 省略,不要新写承诺。 |
| `cta` | 品牌卡上的行动文字。 | 10 | 用脚本里的请求,否则省略。 |
| `topics.text` | 一个简短的话题词。 | 8 | 从脚本里取。不足三个就改用 word-stack。 |
| `focus` | 要突出的那一项的序号,从 0 开始。默认最后一项。 | 数字 | 省略,把主要的一项放最后。 |
| `line` | 突出话题下面的一句短话。 | 24 | 省略。 |
| `cards.title` | 一张卡片上的名称。 | 10 | 用简报原话。 |
| `cards.note` | 这张卡片的短注。 | 18 | 省略。 |
| `messages.text` | 一条对话,用脚本原话。 | 28 | 用脚本里的话。绝不代拟真实人物的发言。 |
| `messages.side` | left 或 right。默认左右交替。 | left/right | 省略。 |
| `payoff` | 片尾的大字一句话,必填。 | 28 | 用脚本里最有力的一句,不改字。 |
| `items.label` | 一行状态的名称。 | 12 | 用简报原话。 |
| `items.state` | 旁边的短状态词,比如“完成”或“延误”。标记由这个词决定。 | 6 | 用简报里的状态。不知道就省略,不显示标记。 |
| `items.status` | 可选,直接指定标记:good 是对勾,delayed 是时钟,cancelled 是叉,unknown 不显示。不能与 state 矛盾。 | good/delayed/cancelled/unknown | 省略。 |
| `detail` | 放大项下面的一句话。 | 36 | 省略。 |
| `start` | 片头占满画面的给定数值。 | 数字 | 必须在原文里。只有一个数值就改用 number-counter。 |
| `end` | 接管画面并停留的给定数值。 | 数字 | 必须在原文里,不许估算。 |
| `author` | 帖子上的名字。用虚构的或提供的。 | 12 | 省略:会显示一条空白。绝不用没写过这段话的真实账号。 |
| `lines.text` | 帖子的一行,用提供的原文。 | 28 | 用原文。 |
| `lines.mark` | 要标出的关键短语。必须与这一行里的文字完全一致。 | 14 | 原文没有强调就省略。 |
| `summary` | 片尾的一句话,必填。 | 32 | 转述原文的要点,并列入推断内容。 |
| `items.name` | 一张产品卡片的名称。 | 8 | 用简报里的名字。 |
| `items.score` | 给定的分数。最高的升起,必须有唯一的最高分。 | 数字 | 不许估算。没有分数就不要用这个效果。 |
| `scoreLabel` | 分数衡量的是什么,显示在卡片下方。 | 10 | 用简报原话,否则省略。 |
| `matchLabel` | 最高分上方的标签,比如“最佳匹配”。 | 8 | 省略:升起本身就说明了。不写空话。 |
| `cardTitle` | 将要碎掉的卡片上的标题。 | 14 | 用脚本里的主题。 |
| `cardLines.text` | 卡片上的一项细节。 | 20 | 用原文。 |
| `flags.text` | 扫描在对应行标出的内容。 | 10 | 原文没有标注就省略。 |
| `captions.text` | 对应图片停留时显示的说明。按图片顺序给出。 | 16 | 可以不给,或少于图片数:这些站就没有说明。 |
| `grade` | 真实的逐像素调色。natural 观感可信,是照片的默认值。filmic 更柔和。warm、cool、punch 是更强的风格。 | natural/filmic/warm/cool/punch | 省略,尤其是在讲色彩准确的时候。 |
| `mascot` | 对象:{"src":"character.png"},透明 PNG,脸要在上方三分之二,路径相对 JSON。最下面八分之一藏在窗台后。 | PNG | 省略:会出现一个原创的剪纸小怪物。没有授权绝不用知名吉祥物。 |

## 不能变通的规则

**不编造数字。** 数据效果只用提供的数值。`source` 里没有的数字,检查脚本一律判失败。只有这几种不需要出处:账单合计(引擎自己相加)、刻度下限 0、百分比的 100。章节号是序号,不是数据。

**运动中的数字只是过渡。** 滚动计数是有意的效果:数字滚到 120 的途中会闪过 112 这样的数,账单也会显示累加中的小计。只有落定的数字才算数值。简报要求只能出现给定数字时,在该段 slots 里写 `"count": false`(适用于 `bars-grow`、`ledger-total`、`ratio-ring`、`gauge-dial`、`unit-grid`、`number-counter`),屏幕上就只会出现最终数字。柱子落定时比例准确,过冲不会超过相邻的更大数值,所以任何时刻排名都不会错。

**简报单薄时:** 用用户自己的话转述事实。绝不编造客户、数字、引语、评价或资历。把所有推断出来的内容列在回复的“推断内容”下面。每个字段怎么处理见“简报单薄时”一列。数据段落没有数字,就用 `phrase-emphasis`。

**没人能回答时:** 继续做,并列出假设。

**要其他时长:** 调整段落数和 `seconds`,单个片段仍是 4 到 8 秒,默认 6 秒;展示段落有自己的时长范围。短片里每次转场都落在已经动起来的下一段上,它的前 28 帧会被替换,所以每处衔接让短片比片段总和短约 0.47 秒(用 `cut` 则不变)。30 秒短片约 6 段,90 秒约 17 段。

**没有真实链接:** 省略 `url`。`action` 用脚本里的请求,或者写“了解更多”。绝不编地址。

**展示段落** 比其他片段长,时长范围见 `assets/catalogue.json`:`chart-scan` 6 到 14 秒,`one-look-stack` 约 7 秒,`corner-drag` 约 7.7 秒,`screen-wall` 约 11 秒。较新的展示段落为 5 到 9 秒。它们可以用 `pictures` 和 `person`;图片围绕中心裁切,或围绕图片上的 `"focus":{"x":0.5,"y":0.3}`;没有时用代码绘制的图片或通用剪纸人物。照片用 `node scripts/cutout.mjs photo.jpg cutout.png` 做成透明人物,只能在 macOS 上运行。`corner-drag` 的读数是设计值,必须在 `readoutLabel` 里写明。

**单独渲染转场效果** 是段落之间的过渡片,4 秒合适。在成片里请用 `transition` 设定衔接。

**换行:** 词语会自动保持完整,10 个汉字或 20 个字母以内的关键词不换行。单独落在一行的字或短词,以及碰到其他文字的色块,检查脚本都会判失败。改写文字,或在想断开的地方加 `\n`。

**可复现性:** 在同一台机器上,重复运行同一条命令,得到的片段和短片逐字节相同,因为衔接是在画布上合成的。换浏览器版本、字体或 ffmpeg 版本,字节可能不同,这一点没有测试。

## 交付物

- `motion/beats.json`:唯一需要改的文件。
- `motion/clips/<id>.mp4`:每段一个片段,1920x1080、30 fps、H.264、yuv420p、无声、4 到 8 秒。
- `motion/film.mp4`:可选,默认小于 10 MB。
- 你的说明:假设、推断内容、重新渲染的命令。

以后要改:改 `beats.json`,运行 `node <skill>/scripts/render.mjs motion/beats.json --out motion --only <id>`,要更新短片再加 `--film`。

## 渲染时间

在制作这个技能的 16 GB Mac 上实测,同时有其他任务,低优先级全尺寸:6 秒片段约 4 秒。全部 46 种效果 about 200 秒。11 段的示例,片段 44 秒,再加 19 秒拼成 60 秒短片。单帧约一秒。文件大小:每个片段约 500 KB,短片 4.6 MB。

## 交付前检查

- [ ] 对文件夹运行 `check.mjs` 退出码为 0,引用它的最后一行。
- [ ] 每段的效果都符合这一段在做的事,没有合适效果的地方用了中性效果。
- [ ] 看过每个最终 MP4 抽出的真实画面,不只是拼图。
- [ ] 比较看得出在比,增长看得出在长,每个意思一眼能懂,想让人记住的那句足够大。
- [ ] 每个 callout-panel 都用了真实图片,圆环都落在所指的内容上。
- [ ] 屏幕上每个数字都在用户原文里,推断内容已经列出。
- [ ] 一个版本一种语言,一条短片一种配色。
- [ ] 没有生成实拍、配音或音乐。
- [ ] 虚构内容已通过 `label` 标明。

## 什么时候不要用

- 需要实拍画面、旁白、音乐,或配合人声的字幕。
- 必须严格使用品牌色和品牌字体:这四套配色就是设计本身。
- 要讲一段连续的长动画或角色故事:这里每个片段只讲一个意思。
- 图表需要坐标轴、多条数据线或精确读数:请用真正的图表,这里最多 8 个点。

## 环境要求

- Node 18 及以上;ffmpeg 和 ffprobe 在 PATH 或 /opt/homebrew/bin。
- 只有渲染需要 Playwright:`npm install playwright`,再运行 `npx playwright install chromium`。如果装在别处,把 `NODE_PATH` 设为那个 `node_modules`。
- `check.mjs` 不依赖任何包。
- 字体都是系统字体。没有 Avenir Next Condensed 或苹方的机器会用 `references/style.md` 里的备选字体,引擎会重新排版,请在那台机器上跑一遍检查。

用在这些流程里

相似技能