
免费
皮影故事
把任何主题变成 35 到 50 秒的绘本短片,关节皮影在灯笼映照的幕布上把它讲清楚。
安装
把“皮影故事”技能安装到 ~/.claude/skills/shadow-puppet。 下载下面每个文件,保存到这个文件夹: https://skilllift.pages.dev/packs/shadow-puppet/SKILL.zh.md → SKILL.md https://skilllift.pages.dev/packs/shadow-puppet/references/style.md → references/style.md https://skilllift.pages.dev/packs/shadow-puppet/references/props.md → references/props.md https://skilllift.pages.dev/packs/shadow-puppet/references/prop-sheet.png → references/prop-sheet.png https://skilllift.pages.dev/packs/shadow-puppet/assets/engine.html → assets/engine.html https://skilllift.pages.dev/packs/shadow-puppet/assets/core.js → assets/core.js https://skilllift.pages.dev/packs/shadow-puppet/assets/props.js → assets/props.js https://skilllift.pages.dev/packs/shadow-puppet/assets/scene.template.json → assets/scene.template.json https://skilllift.pages.dev/packs/shadow-puppet/scripts/check.mjs → scripts/check.mjs https://skilllift.pages.dev/packs/shadow-puppet/scripts/render.mjs → scripts/render.mjs https://skilllift.pages.dev/packs/shadow-puppet/scripts/assemble.mjs → scripts/assemble.mjs 然后读一遍 SKILL.md,告诉我它是做什么的,并提醒我开一个新会话。
解压到 ~/.claude/skills
同一个技能,不同的需求
左边是预览。右边由另一个 Agent 按不同需求制作,它只有安装好的技能,没看过预览。
这是按虚构需求做的一次测试。系统字体不同时,字形可能略有差异。
把一个主题变成 35 到 50 秒的无声绘本短片,并附分幕计划,用皮影戏的方式演出:带铜铆钉和操纵杆的关节剪影人物,在灯笼映照的发光幕布上行走、比划,用虚实表现远近,字幕写在一道水墨笔触上。包含确定性渲染引擎、60 个代码绘制的道具(包括月相正确的月亮、地球、轨道和箭头路径、带标签的示意图板),支持 16:9 和 9:16。当用户想要一段温暖的短讲解、小故事或道理视频,或者点名要皮影、绘本风格时使用。
交付前必须通过
node scripts/check.mjs scene.json退出码为 0。- 对完整尺寸的成片运行
node scripts/check.mjs story.mp4 --stills frames,不加--test,退出码为 0。 - 每一幕的样张我都看过,每个皮影我都能一眼叫出名字。
- 我看过最终 MP4 的静帧,每幕一张,并核对了画面里的事实。
- 每句字幕都来自用户给的事实或普通常识,没有编造数字、客户、引语或资历。
- 每幕一个想法,并且有东西在动。
- 全片一种语言,
idea字段也一样。 - 推断的句子和假设已经写在回复里。
- 如果用户在等,已经说明实际渲染时间。
阅读完整 SKILL.md
---
name: shadow-puppet
description: 把一个主题变成 35 到 50 秒的无声绘本短片,并附分幕计划,用皮影戏的方式演出:带铜铆钉和操纵杆的关节剪影人物,在灯笼映照的发光幕布上行走、比划,用虚实表现远近,字幕写在一道水墨笔触上。包含确定性渲染引擎、60 个代码绘制的道具(包括月相正确的月亮、地球、轨道和箭头路径、带标签的示意图板),支持 16:9 和 9:16。当用户想要一段温暖的短讲解、小故事或道理视频,或者点名要皮影、绘本风格时使用。
version: 1.0.0
---
# 皮影故事
样式都在 `assets/` 里。你只需要写一个文件:分幕 JSON。台词、道具和动作由你决定,引擎不要动。`scripts/check.mjs` 发现引擎被改过就会报错。
选角之前,先读 `references/props.md`,再看一眼 `references/prop-sheet.png`。需要具体数值时查 `references/style.md`。
## 需要问用户的信息
缺什么一次问完,放在同一条消息里。
必需:
1. 主题,以及观众看完应该明白什么。
2. 要用的事实:步骤或要点,用用户自己的话,或者来自用户给的资料。
可选:
3. 语言:中文或英文,每个版本只用一种。两种都要就做两个版本。
4. 画幅:16:9(默认)或 9:16。
5. 时长:35 到 50 秒之间。
6. 用户自己有权使用的音乐文件。没有就是无声片,只有屏幕字幕,不带音轨。
## 步骤
1. 把 `assets/scene.template.json` 复制到工作目录,命名为 `scene.json`,替换掉所有 `FILL`,按需要增加步骤幕。
2. 写分幕:标题、2 到 6 个步骤、道理、温暖的收尾。每幕一个想法,字要少。
3. 对照 `references/props.md` 给每一幕选道具,并给主角一个 `do` 动作。
4. 运行 `node scripts/check.mjs scene.json`(竖屏加 `--format 9:16`),修好它报出的每个问题。不要放宽限制,也不要改检查脚本。
5. 先出缩小尺寸的样张:`node scripts/render.mjs scene.json proofs --proof --scale 0.5`。几秒钟就好,每幕两张。**每一张都要亲眼看。** 逐个道具问自己:一个陌生人能叫出这个形状的名字吗?不能就换。重复第 3 到 5 步直到全部通过。反复修改都在这一步做,不要反复渲染完整视频。
6. 准备好之后渲染一次成片:`node scripts/render.mjs scene.json out/story.mp4`。竖屏加 `--format 9:16`,配乐加 `--music song.mp3`。一次只渲染一部。
7. 运行 `node scripts/check.mjs out/story.mp4 --stills frames`。它会读取真实文件(编码、尺寸、时长,并解码画面检查动作和字幕),再为每幕写一张清晰的中段画面。分幕计划存在片子里,改名或挪位置后仍然能检查。
8. 把 `frames` 里的每张都看一遍。页面样张没问题,不等于 MP4 没问题。如果画面本身带有事实(比如月相),就在这些帧上核对。
试验时:
- 短测试:`node scripts/render.mjs scene.json out/short.mp4 --test` 每幕取 1.5 秒。`--scenes 2,5` 只完整渲染这几幕。两者都用 `node scripts/check.mjs out/short.mp4 --test` 检查,会跳过时长和故事结构规则。只有几幕的分幕文件也可以用 `check.mjs scene.json --test`。
- 单帧:`node scripts/render.mjs scene.json out/frame.png --frame 240` 重新渲染这一帧并打印 SHA-256。同一帧每次字节都相同。
- 其他渲染参数:`--scale 0.5`(缩小尺寸)、`--every 2`(隔帧)、`--crf 24`(数值越大文件越小)、`--format 9:16`、`--music 文件`、`--proof`。
**实际渲染时间**(Apple 芯片 Mac,16 GB 内存,低优先级,ffmpeg 两线程):48 秒的 16:9 示例用了 52 秒,41 秒的 9:16 短片用了 47 秒,大致比片长略多。机器慢会更久,开始前先告诉用户。样张只要几秒。
## 字段说明
每个字段只有一个含义、一个上限,都由检查脚本把关,未知字段会被拒绝。
### 整部片
| 字段 | 含义 | 上限 | 信息太少时 |
|---|---|---|---|
| `lang` | 所有可见文字的语言 | `en` 或 `zh` | 跟用户的语言一致 |
| `format` | 画幅 | `16:9` 或 `9:16` | `16:9` |
| `sample` | 每帧都显示的小标签,只用于示例 | 16 个汉字或 40 个英文字符 | 不是示例或示意内容就不要写 |
### 每一幕
| 字段 | 含义 | 上限 | 信息太少时 |
|---|---|---|---|
| `kind` | 这一幕的作用 | 第一幕 `title`,接着 2 到 6 个 `step`,一个 `lesson`,最后 `close`。总共 6 到 10 幕 | 标题、3 个步骤、道理、收尾 |
| `seconds` | 停留时间 | 每幕 3.5 到 9 秒,总共 35 到 50 秒。中文至少 1.4 + 字数 / 6,英文至少 1.4 + 词数 / 3 | 每幕 6 秒 |
| `idea` | 这一幕唯一的想法,写进计划,不上屏 | 70 个字符 | 用户对这一点的原话 |
| `caption` | 水墨条上的字幕。片子无声,每幕都必须有 | 24 个汉字,或 12 个英文词且不超过 70 字符。最多 2 行,不能重复。中文用全角标点 | 复述用户给的事实,不添加用户没说过的数字或说法 |
| `title` | 幕布上的大字,只用于 `title` 和 `close` 幕 | 14 个汉字或 40 个英文字符,最多 2 行 | 用户说的主题;收尾用一句感谢 |
| `light` | 灯光氛围 | `amber`、`dawn`、`dusk`、`night` | `amber` |
| `ground` | 人物脚下的剪纸地面 | `grass`、`hills`、`cobbles`、`sea`、`none` | `cobbles` |
| `cast` | 出场的皮影 | 1 到 6 个 | 说书人加一块木牌(见下文) |
### 每个皮影(`cast` 的每一项)
| 字段 | 含义 | 上限 | 信息太少时 |
|---|---|---|---|
| `prop` | 用哪个道具 | `references/props.md` 里的 id | `storyteller`、`sign` |
| `as` | 这个剪影在这一幕表示什么 | 必须是该道具那一行里的词,其他词都会报错 | 道具本身的名字,如「说书人」「木牌」 |
| `x`、`y` | 位置,占舞台的百分比。`x` 从左到右,指皮影的中心。`y` 是皮影底部离地面的高度:0 站在地上,100 到舞台顶部。16:9 中 y 10 约 76 像素,9:16 中约 125 像素 | 0 到 100。被裁切时检查脚本会提示 | 人物 `x` 22,木牌 `x` 68,`y` 为 0 |
| `size` | 最长边的大小 | `s`、`m`、`l`、`xl`。形状细的要用大一号,检查脚本会提示 | 人物和木牌都用 `l` |
| `plane` | 远近 | `far`(远景,很虚)、`mid`、`near` | `near` |
| `do` | 动作 | 见下文。每幕至少有一个看得见的动作,在 `near` 或 `mid` 层 | 人物用 `point`、`think`、`raise` 或 `nod`,木牌用 `bob` |
| `to` | 动作的终点 | `walk`、`fly` 必须有 `{"x":…}`;`rise`、`sink`、`fall` 可选 `{"y":…}` | 不走动就不写 |
| `from`、`towards` | `enter` 从哪边进,`exit` 往哪边出 | `left` 或 `right` | 不写 |
| `at`、`for` | 动作开始时间和时长,单位秒。见「时间和逐个出现」 | 不超出这一幕 | 不写 |
| `show`、`hide` | 出现的秒数和离开的秒数,对所有道具有效 | 不超出这一幕,至少停留 1 秒 | 不写 |
| `flip` | 不移动时面朝左 | true 或 false。行走、飞行、沿线行进时无效,因为移动的皮影总是朝着前进方向。月亮不能用 | 不写;需要时让站着的人物面向木牌 |
| `gel`、`gelTo`、`gelAt`、`gelFor` | 染色皮革的颜色、要变成的颜色,以及变色时间 | `green`、`gold`、`orange`、`red`、`plum`、`blue`、`teal`、`cream`。只用于标了 gel 的道具 | 不写。只有颜色本身是重点时才用 |
| `label` | 皮影上方的小标签,任何时刻都不能碰到其他东西 | 6 个汉字或 14 个英文字符 | 不写 |
| `text` | `sign` 上的字 | 6 个汉字或 14 个英文字符。木牌必填,其他道具不能用 | 用户原话里的一个词 |
| `p` | 9:16 专用覆盖:`{"x","y","size","to"}` | 上限同被覆盖的字段 | 检查脚本报竖屏裁切时再用 |
`do` 的动作:
- 所有皮影:`still`、`sway`、`enter`、`exit`、`rise`、`sink`、`fall`、`fly`、`float`、`bob`、`hop`、`grow`、`shake`、`spin`。
- 有腿或有轮子的:`walk`。
- 只限人物:`point`、`wave`、`bow`、`think`、`raise`、`nod`、`carry`。
- 只限标了 work 的道具:`work`。
- 沿轨道或箭头走:`travel`。轨道、箭头和图板:`draw`。
## 带参数的道具
这些道具能把想法本身演出来,先用它们,再考虑用字。所有数值都会被检查。
**moon(月亮)**:可以画出周期里任何一天的正确亮面。暗面是墨色,亮面用染色皮革(默认 cream)。
| 字段 | 含义 | 上限 |
|---|---|---|
| `phase` | 月相在周期中的位置:0 新月,0.125 蛾眉月,0.25 上弦月,0.375 盈凸月,0.5 满月,0.625 亏凸月,0.75 下弦月,0.875 残月,1 新月 | 0 到 1,默认 0.12。`as` 必须对得上:phase 0.1 却写「满月」会报错 |
| `phaseTo`、`phaseAt`、`phaseFor` | 在这一幕里变换月相:终值、开始秒数、持续秒数 | 0 到 1。要沿周期向前走 |
| `hemisphere` | `north`(默认):上半月亮面在右,下半月亮面在左。`south` 左右相反 | 信息太少时用 `north`,并在回复里说明 |
如果是从外部看月亮(画面里有太阳),亮的一半必须朝向太阳:太阳在左用 phase 0.75,太阳在右用 0.25,不管月亮走到轨道哪里。月亮不能用 `flip`。
**sun(太阳)**:形状固定,配 `gel: "gold"`。**earth(地球)**:带镂空陆地的星球,用 `gel: "blue"` 才像地球,`do: "work"` 让它转动。**globe(地球仪)**:同样的球,放在桌面支架上。
**orbit(轨道)**和 **arrow(箭头)**是引导线:贴在幕布上的细线,用舞台百分比定位,没有操纵杆,也没有 `size`。皮影可以从上面经过。
| 字段 | 含义 | 上限 |
|---|---|---|
| `id` | 名字,让皮影可以沿着它走 | 需要行进时必填 |
| `x`、`y` | 轨道的中心;箭头的起点 | 0 到 100 |
| `rx`、`ry` | 轨道半径:占舞台宽度、高度的百分比 | 轨道必填,不能超出屏幕 |
| `start`、`clockwise` | 一圈从哪里开始,单位度(0 在右,90 在上),以及方向。默认逆时针,也就是从北面看月球的方向 | 仅轨道 |
| `to`、`bend` | 箭头终点 `{"x","y"}`,以及弯曲度 -50 到 50 | 仅箭头 |
| `do` | `still` 直接完整显示;`draw` 在 `for` 秒内画出来 | 不能用其他动作 |
| `gel` | 线条颜色,比如用 gold 表示阳光 | 可选 |
| `label` | 显示在右边缘外侧 | 6 个汉字或 14 个英文字符 |
让皮影沿引导线走:`"do": "travel", "along": "<id>"`,可选 `"span": [0, 1]` 表示走路径的多少(0.5 是半圈,2 是两圈),也可以加 `at`、`for`。皮影的中心贴着线走。行进中的皮影不要加标签,它会压到别的东西;把标签加在引导线或中心的物体上。
**panel(图板)**:给没有对应道具的概念用的示意图,几块牌子用箭头连起来,装在一根横杆上。
| 字段 | 含义 | 上限 |
|---|---|---|
| `boxes` | 按顺序的标签 | 2 到 4 个,每个 6 个汉字或 14 个英文字符 |
| `layout` | `row`、`column` 或 `cycle`(cycle 需要 3 或 4 个) | 信息太少时用 `row`;9:16 用 `column` 或 `cycle` |
| `w` | 宽度,占舞台宽度的百分比,代替 `size` | 20 到 100。字不能小于 30 像素 |
| `do` | `draw` 在 `for` 秒内逐个显示牌子 | 信息太少时用 `draw` |
```json
{ "prop": "panel", "as": "流程", "boxes": ["输入", "处理", "输出"], "x": 50, "y": 10, "w": 60, "do": "draw", "at": 0.5, "for": 3.5 }
```
## 时间和逐个出现
没有特别说明时,皮影从这一幕开始就在幕布上。下面的做法对所有道具、木牌和图板都有效:
- `show`:出现的秒数,0.35 秒内贴上幕布。在此之前什么都不画:没有形状、没有操纵杆、没有标签。
- `hide`:离开的秒数。
- `grow` 加 `at`:算作出现,到 `at` 之前什么都不显示。
- 其他动作的 `at`、`for` 只决定动作什么时候做,皮影在那之前仍然看得见。要隐藏就加 `show`。
要让三样东西依次出现,把它们的 `show` 至少错开 1.2 秒。
## 没有合适的道具时
这很常见。按顺序做:
1. 再查一遍 `references/props.md`,「系统」「想法」「成本」这类词都列在里面。
2. 如果这个想法有组成部分或先后顺序,用 **panel**;有东西在移动,再加 `arrow` 或 `orbit`。
3. 还是不行,就用**中性方案**:一块写着这个词的 `sign`,加一个指着它的 `storyteller`。
```json
{ "prop": "sign", "as": "木牌", "text": "记录", "x": 68, "size": "l", "do": "bob" },
{ "prop": "storyteller", "as": "说书人", "x": 22, "size": "l", "do": "point" }
```
绝不用「差不多像」的形状。树不能代表肺,硬币不能代表太阳。差一点的道具会误导观众,木牌不会。
## 遇到这些情况
- **信息太少。** 复述用户给的事实,绝不编造,按上面「信息太少时」一栏来写。回复里列出所有推断出来的句子。整部片都用中性方案也能通过检查,也可以交付。
- **没人能回答问题。** 直接做,交付时列出你的假设。
- **用户想要别的时长。** 增减步骤幕和秒数。短于 35 秒或长于 50 秒不在本技能范围内,要直说,并提供最接近的时长,或拆成几部。
- **没有真实链接。** 不要编。收尾不需要网址。用户给了网址,除非特别要求,不放进画面,写在发布文案里。
- **主题里有你无法核实的事实。** 只用用户给的内容或常识,说明哪些是哪些;如果片子只是示意,就写上 `sample`。
- **画面本身在陈述事实。** 月相、方向、先后顺序都是说法,要像字幕一样核对。主题没说南北半球时用 `north`,并说明。
- **木牌要放到地面以上。** 木牌有两条腿,悬空很怪。改用物体的 `label` 或 `panel`。
- **用户想要配音。** 本技能不做配音,只能带上用户的音乐文件。可以把分幕计划当稿子,让用户在剪辑软件里加旁白。
## 交付物
- `story.mp4`:H.264,yuv420p,30 fps;1920x1080,竖屏为 1080x1920。除非提供音乐,否则无声。
- `story.plan.md`:分幕计划。
- `story.html`:自包含的单文件页面,打开就播放。
- `scene.json`:源文件,方便以后修改。
## 交付前检查
- [ ] `node scripts/check.mjs scene.json` 退出码为 0。
- [ ] 对完整尺寸的成片运行 `node scripts/check.mjs story.mp4 --stills frames`,不加 `--test`,退出码为 0。
- [ ] 每一幕的样张我都看过,每个皮影我都能一眼叫出名字。
- [ ] 我看过最终 MP4 的静帧,每幕一张,并核对了画面里的事实。
- [ ] 每句字幕都来自用户给的事实或普通常识,没有编造数字、客户、引语或资历。
- [ ] 每幕一个想法,并且有东西在动。
- [ ] 全片一种语言,`idea` 字段也一样。
- [ ] 推断的句子和假设已经写在回复里。
- [ ] 如果用户在等,已经说明实际渲染时间。
## 不适合的情况
- 需要图表或屏幕上要有精确数字的内容。
- 需要真人、真实产品或某个品牌自身样式的内容。
- 严肃新闻、医疗或法律指导,绘本语气可能误导观众。
- 时长不在 35 到 50 秒之间,或者需要现成旁白的片子。
- 指定知名角色。这里的人物全部是原创的通用形象。
## 运行要求
- Node 18 或更高版本。
- Playwright 和 Chromium:`npm install playwright`,然后 `npx playwright install chromium`。如果装在别处,把 `NODE_PATH` 指向那个 `node_modules`。
- PATH 里要有 ffmpeg 和 ffprobe,或者用 `FFMPEG` 指定 ffmpeg 路径。只检查分幕文件或页面时不需要它们。
- 约 1 GB 空闲内存。一次只渲染一部,默认低优先级,ffmpeg 两线程。
- 字体用系统字体栈;没有对应字体的机器会回退到衬线字体,渲染时会按实际字体重新测量。



