---
name: script-to-doodle-animation
description: >
  当用户提供一段中文文稿、想做成"简笔画小人讲解动画"或"手绘解说视频"时使用。
  本技能自动：(1) 用 edge-tts 把文稿配成旁白并提取词级时间戳；(2) 由 Agent 担任导演，
  把文稿改编成多角色/道具/运镜的分镜（storyboard），角色会走位、传递物品、置身于
  店铺/银行/城市等简笔场景；(3) 所有动作对齐到旁白真实时刻；(4) 经 After Effects
  或 HTML 双后端渲染出片。AE 路径需要 After Effects 已打开（MCP 桥或 AfterFX -r 通道）。
---

# 文稿 → 简笔画讲解动画

把一段中文文稿变成"多角色简笔小人 + 场景道具 + 运镜 + 弹字 + 字幕"的讲解动画。
旁白由 edge-tts 合成，所有动作对齐旁白真实时间戳。

以下命令均在本技能根目录执行。Python 命令本文写作 `py -3.14`，若本机无 py 启动器或该版本，
换成任一 Python 3.10+ 调用方式（如 `python` / `python3`）即可。

## 两种模式

- **导演模式（默认，推荐）**：你（Agent）阅读文稿后亲自编写分镜 `storyboard.json`——谁出场、
  站在哪、走到哪、把什么递给谁、镜头跟谁。画面叙事能力完全取决于这份分镜的编排质量。
- **简单模式（退化路径）**：跳过分镜，由 `plan.py` 规则分类出单人原地姿势。只适合快速冒烟
  测试，正式出片一律用导演模式。

## 硬性规范（每次开工前读，违反即返工）

### 原创度 ≥50%——禁止"换皮复用"
上一题材的素材可以借底层骨架，但**不能借创意**。每个新题材：

- **必须新建专属道具**：复制 `assets/props.json` 为 `out-<项目>/props.json`，为本题材核心概念
  新增 primitives 道具（渲染器按 primitives 自动绘制，**加道具不需要改渲染器代码**）。
  本片所用素材里"本任务新建的"（道具 / 角色姿势 / 特效 / 叙事母题）占比必须 **≥50%**。
- **禁止套用 econ 母题**：「小人沿街走过一排店铺 + coin 手手相传 + 镜头一路向右」是
  "经济如何运行"的专属隐喻，换个题材直接搬 = 换皮。新题材要有自己的视觉隐喻：
  抽象概念 → 提取核心机制 → 设计专属视觉符号。
  例：商业杠杆=撬杆/咬合齿轮；数据流=管道/水流；复利=滚雪球；平台撮合=两侧节点连线；
  风险=天平/裂缝。母题决定全片镜头与道具走位，先定母题再写分镜。
- 允许复用的是"画法"（rig 小人、映射公式、渲染器、burst/dust 等通用特效）；
  不允许复用的是"这片讲什么、用什么视觉打比方"。

### 提速——砍返工，不砍创意
新素材该花的时间要花；浪费一律消灭：

- **文稿一次定稿**：按 ~2.8 字/秒估目标字数（3 分钟≈480 字），先估后 `tts.py`，不来回重跑配音。
- **契约一次读够**：动词表 / 坑表 / 渲染公式都在 `docs/storyboard-spec.md`，别反复派 agent 侦察同一份代码。
- **渲染走可靠路**：HTML 后端（`render_mp4.mjs`，1080p + 崩溃自愈，纯 E 盘）是首选与兜底；
  AE 后端仅在 **C: 有数 GB 空闲且需人工精修**时跑——AE 引擎在 C:盘满时根本起不来，
  别在 aerender 卡死上反复试（aerender 还会与开着的 GUI AE 抢 license，先 `Stop-Process AfterFX`）。
- **产物落空间充足的盘**：帧序列+成片几百 MB 起步；系统盘剩余空间不足时 AE 引擎甚至无法启动，
  out/ 目录一律放数据盘。

### 长片不退化（≥60s 必守，否则塌成 PPT 说教）
短片精雕 8 幕就够；长片（3 分钟≈40 句）若按"短片拉长"做，必然密度稀释成 boss 站桩指点。
**实测对比（反面教材）**：好片 econ（36s）密度 1.89 动词/秒、运动占比 25%、5 角色互相走位传递；
退化片（173s）密度 0.73、运动 6%、1 角色独角戏对着道具解说。硬指标：

- **密度 ≥1.2 动词/秒**：每句旁白期间画面都要发生事，不许站着说。
- **运动叙事 ≥15%、说教 ≤35%**：walk/run/give/hops/emerge 是主菜，point/nod/emote 只是调味。
  靠"角色走位 + 贯穿物在角色间手手相传"撑画面（econ 的灵魂），不是靠 boss 指着道具解说。
- **多角色 ≥3 且有实质互动**：禁止独角戏。任何题材都能多角色——商业题材有客户/学生/老板/平台用户，
  让他们出场、走位、give、接收。**装置是舞台，角色互动才是叙事**；道具再原创，没人在里面"做事"就是 PPT。
- **贯穿物连续流动**：coin 类要像 econ 那样一条线 give/hops 流过多个角色，
  不要每次 emerge 又弹回原点的离散重复。
- **章节节奏**：长片按内容分 3-5 章，每章铺垫→高潮有起伏，章节间用 wide/转场分隔，避免 40 句匀速平铺。
- ⚠️ **原创母题 ≠ 砍角色砍运动**：换专属道具的同时务必保留多角色与走位传递，别为"原创"做成独角戏。

## 工作流程（导演模式）

### 1. 配音 + 对时 + 分幕

```
py -3.14 scripts/tts.py <script.txt> out/voice.mp3 out/timing.json
py -3.14 scripts/plan.py <script.txt> out/timing.json out/plan.json
```

plan.json 提供每幕 start/end、字幕、关键词卡点时刻（弹字仍由它驱动）。

### 2. 当导演：编写 storyboard.json（本技能的灵魂步骤）

**先通读 `docs/storyboard-spec.md`**（schema、动词表、时间引用语法、渲染公式），然后为文稿
创作分镜。编排要领：

- **给每个被提到的实体一个落点**：文稿说到面包师傅，就该有个 baker 站在面包店前；说到银行，
  就该有 bank 道具。角色放进 `cast`，场景放进 `props`（道具库见 `assets/props.json`：
  house/shop/bank/coin/cake/skyline/path/tree，shop 和 bank 支持中文招牌 label）。
- **让"物"当主角**：讲解类文稿常有一个贯穿物（钱、水滴、数据包……），用 coin 类物品 +
  give/emerge/orbit/hops 动词让它在角色间流动，观众的眼睛会跟着它走。
- **横向展开舞台**：把地点沿世界 x 轴排开（间距 800~1000），镜头随剧情一路推进，
  比固定机位生动得多。fixed 看群像，follow 跟主角。
- **时间引用钉到词**：动作时刻用 `sN.start+偏移` / `kw:关键词` / `w:词`，不许写裸数字估时。
- **每幕至少一个画面事件**，宁可加 bounce/emote 小动作，不要让任何一句旁白期间画面静止。

### 3. 解析分镜 → 渲染轨道

```
py -3.14 scripts/resolve.py out/storyboard.json out/plan.json out/timing.json out/resolved.json
```

resolve.py 负责对时和把动词展开成纯数值轨道，并校验引用（地名/角色/关键词不存在会报错，
carrier 交接对不上会告警——告警必须处理，那通常意味着分镜漏写了一次传递）。

### 3.5 密度自检（强制 gate，≥60s 必跑）

```
py -3.14 scripts/density_check.py out/storyboard.json out/timing.json
```

算视觉密度/运动占比/说教占比/角色数/静止幕。**[WARN] 必须改分镜清零再进渲染**——
这是防长片退化成"boss 站桩指点"的硬闸（阈值由 econ 好片通过 / 退化片报警标定）。
报警常见修法：加角色互动（give/walk）、把 point/nod 换成走位、给静止幕补画面事件。

### 4. 渲染（双后端，可都跑）

**HTML 后端**（快，单文件可分享，迭代首选）：

```
py -3.14 scripts/build_html2.py out/resolved.json out/plan.json assets/rig_spec.json assets/props.json out/voice.mp3 out/doodle2.html
node scripts/render_mp4.mjs out/doodle2.html out/timing.json out/voice.mp3 out/demo2.mp4
```

**After Effects 后端**（出 .aep 工程，可继续人工精修）：

```
py -3.14 scripts/build_ae4.py out/resolved.json out/plan.json assets/rig_spec.json assets/props.json <voice.mp3绝对路径> out/build4.jsx
```

执行 jsx 三选一：after-effects MCP 工具；AE 菜单 File > Scripts；
`AfterFX.exe -r <runner.jsx>`（无人值守用 runner 包裹：开脚本写文件权限 → suppressDialogs →
try/catch 写日志 → app.project.save，模板见 `assets/ae_runner_template.jsx`）。
渲染用 aerender（AE 2026 默认输出模块直接出含音轨的 h264 mp4）。

### 5. 视检（强制，渲染器不可信任自己）

ffmpeg 在每幕中点抽帧，亲眼 Read 检查：
- [ ] 所有实体共用一条地面线（角色、建筑、地面线必须同一 y——坐标映射不统一是最常见回归）
- [ ] 小人不散架、移动时腿在交替、朝向与移动方向一致
- [ ] 文稿提到的实体在对应幕的画面里（面包师那句有面包师，银行那句有银行）
- [ ] 关键词弹字落在被念出的帧；字幕逐句正确
- [ ] 镜头里主体不出画；隐藏角色无残留图层（"鬼点"）

不合格就改 storyboard 或渲染器重跑，直到全过。

## 简单模式（仅冒烟）

```
py -3.14 scripts/build_html.py out/plan.json out/timing.json assets/rig_spec.json out/voice.mp3 out/doodle.html
py -3.14 scripts/build_ae.py  out/plan.json out/timing.json assets/rig_spec.json <voice.mp3绝对路径> out/doodle_build.jsx
```

## 环境要求

- `py -3.14` + `edge-tts` + `fonttools`+`brotli`（HTML 端字体子集化内嵌）；node 18+ + playwright（HTML 渲 mp4）；ffmpeg（PATH）
- 素材已内置 assets/：GSAP 3.13 免费插件五件套（physics2d/customease/customwiggle/custombounce/drawsvg）、霞鹜文楷 LXGWWenKai-Regular.ttf（构建时自动子集化）、props.json 道具库
- After Effects 2024+（仅 AE 后端）。ExtendScript 是 ES3，生成器已规避已知坑
  （TextDocument 3 值色、anchor[0,0]+显式 Position、无 alert、纸底 solid）

## 参考

- 分镜规格（必读）：`docs/storyboard-spec.md`
- 端到端教程：`examples.md`；样例分镜：`examples/storyboard-econ.json`（"经济是怎么运行的"，
  5 角色 6 道具 8 幕，含钱币贯穿全片的完整编排，照着学）
- 小人关节规格：`assets/rig_spec.json`；道具库：`assets/props.json`
