Communitygithub.com

wlr2/toon-reel

使用 toon-reel-engine 制作竖屏(9:16, 1080×1920, 30fps)卡通故事短片,适用于 Reels / TikTok / Shorts。涵盖脚本编写、剧集文件、Skia 卡通风格、三层布光、镜头指导、表演、帧检查、音效、混音及最终导出。当用户需要制作新的短片、剧集、微型故事、传说重述或动画短片时使用。

toon-reel 是什么?

toon-reel 是一个基于 Python 的纯代码动画短片引擎,专为生成 9:16 竖屏、1080×1920 分辨率、30fps 的卡通风格短视频而设计,适用于 Reels、TikTok 和 Shorts 平台。引擎的核心思想是“每一帧都是时间 T 的纯函数”,完全摒弃了传统的时间轴编辑器和关键帧 UI,所有角色、场景、灯光和摄像机都通过 Python 代码定义。 该技能提供了一套完整的工作流程:从脚本创作(十步法)、时间线生成、角色与场景设计,到三层布光(冷环境光+面部柔光+暖实用光)、镜头运动、表演动作的链式编排,再到严格的帧检查(两轮检查)、语音处理、音效混音和最终导出(-14 LUFS 标准化)。引擎内置了“The Lamp”示例模板和“The Man at the Window”完整案例,方便快速上手。 该技能支持本地或付费 TTS 语音合成,通过`find_phrases.py`精确对齐语音与动画时间线。所有动画块(角色姿势、镜头运动、布光参数)都通过配置文件(如`looks.py`、`scenes.py`和`cues.py`)驱动,确保检查通过后才进入主渲染。该引擎完全开源,托管在 GitHub 仓库 wlr2/toon-reel-engine,不依赖任何商业许可证工具,仅需 Python、FFmpeg 和必要的 Python 包。关键功能包括:自动异常检测(关节、穿透、遮挡)、分帧检查图(gapped sheets)、多进程并行渲染、以及完整的音视频导出管线。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/wlr2/toon-reel-engine/tree/HEAD/skills/toon-reel

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Toon reel

你正使用 toon-reel-engine 来执导并制作一部短动画故事。所有内容都是 Python 代码:角色、场景、灯光和摄像机都是代码,每一帧都是时间 T 的纯函数。没有时间轴编辑器,也没有关键帧 UI。你编写数据(关键帧、镜头表),然后 查看每一帧。

引擎布局(请保持此结构,其相对导入依赖于此):

tools/toon/            引擎:toon.py(渲染器)、rig.py(角色)、anim.py(时间)、cast/、props/、sets/(组件库)
tools/                 sound.py(依据提示生成音轨)、mix_check.py(语音清晰度检查)、finish.py(-14 LUFS 导出)、
                       thumb.py(封面图)、find_phrases.py(解说录音中各短语的时间位置)
episodes/starter/toon  模板:"The Lamp",12.5 秒,四个镜头,一个房间,一个人物。拷贝此文件夹开始制作。
episodes/window/toon   完整示例:"The Man at the Window",50 秒,13 个镜头,两个世界,一个反转。
episodes/jeff、episodes/smilingman   完整示例和组件库的支持模块(不可作为独立剧集运行)

命令。 下面的 python 指已安装 requirements.txt 中依赖的解释器(Windows 上是 py)。剧集本身的脚本(reel.py、build_tl.py、finalize.py)在剧集文件夹 episodes/<name>/toon 中运行。工具从项目根目录运行:python tools/sound.py episodes/<name>/toon。

第一步:查找或设置引擎

在用户自己的项目文件夹中工作,绝不能进入插件的安装文件夹(更新时会被替换)。

  1. 如果工作文件夹中已有 tools/toon/toon.py,直接使用。
  2. 否则,引擎随此技能一起提供。其根目录位于此技能基础目录向上两级(<skill dir>/../..):包含 tools/、episodes/、requirements.txt 和 .gitignore。将这 4 项复制到工作文件夹中,保持目录结构,并告知用户已完成复制。如果该文件夹没有 tools/(说明技能被单独复制),则克隆 https://github.com/wlr2/toon-reel-engine。
  3. pip install -r requirements.txt,并检查 ffmpeg -version 是否能正常工作(需版本 5.1 或更高)。字幕需要 Arial Black 字体,或设置 TOON_FONT 为一个粗体无衬线 .ttf 文件。
  4. 在构建任何内容之前,先验证设置是否成功:从 episodes/starter/toon 运行 python build_tl.py,然后 python reel.py --frame 5.0 必须生成文件 review/_f5.00.png。

流程是固定的

脚本 -> 时间线 -> 角色造型表 + 场景帧 -> 封锁表演 -> 检查(两轮) -> 预览 -> 主渲染 -> 音效 -> 混音 -> 导出 -> 后期处理。

在检查通过并记录日志之前,绝不要开始主渲染。在开始动画之前,先向用户展示角色造型表和一张场景帧;在全分辨率预览之前,展示一张带标注的关键帧图。在需要花钱的地方(付费 TTS、付费音效、云渲染)之前先征求用户同意。

1. 脚本(references/script.md)

十步法:从最具体的矛盾开始,一个主要问题,一系列后果,每隔几秒就有一个变化,内容适合朗读和动画,有一个动态的中段,一个有意义且包含标志性台词的结尾,诚实的框架(例如,对于 creepypasta 风格使用“AN INTERNET HORROR STORY”),一个带时间的镜头表,然后进行保留编辑。如果用户提供了脚本或节拍表,以他们的文字和规格为准,而不是这里的内置规则:永远不要重写他们的台词,可以提出修改建议并引用你要修改的内容。

交付物:SCRIPT.md(三个钩子 + 选择,完整旁白,带时间的镜头表,字数统计)和 script.py。

2. 时间线,然后是声音

  • script.py 包含 PHRASES(每句台词的放置位置、文本、字幕块,其中红色关键词用 [word] 标记)和 MARKS(以秒为单位的故事节拍,将成为镜头边界)。
  • python build_tl.py 会生成 timeline.json(包含 total、marks、lines)。短片只读取 timeline.json。 在模板示例中,它在任何音频存在之前就能工作:短语时长根据字数估算,因此你可以先规划画面。
  • 声音需要每个说话者一个录音文件,48kHz 单声道,可以来自任何 TTS 或麦克风(本仓库不包含任何 TTS;ElevenLabs 是付费的,Kokoro 是免费的本地库)。永远不要为了适配时长而加速录音:而是应剪掉一个节拍。在发送给 TTS 的文本中,将数字拼写为单词。
  • python tools/find_phrases.py take.wav 会打印录音中每个短语的 (start, end) 时间。将它们填入 PHRASES 并重新运行 build_tl.py:它会切出短语、放置它们并生成 audio/narration.wav。然后重新检查每个镜头:实际短语长度与估计值不同。
  • 技能附带的 build_tl.py 文件处理单个旁白者。若有多个说话者,则每个说话者保留一个录音文件,并将说话者添加到每个短语中(这需要对 build_tl.py 做一点小改动)。
  • 针对 TikTok 的脏话处理:在单独的音轨中进行哔声处理,并在字幕中用星号代替(f***ing)。

3. 剧集文件(references/engine.md)

文件职责
script.py台词、字幕块、标记
build_tl.py生成 timeline.json(以及 audio/narration.wav)
looks.py角色:每个造型是 rig.LOOK 中的一个字典
scenes.py世界:场景几何体、灯光、谁在时间 T 在哪里、表演轨道
reel.py镜头(SHOTS)、字幕、render(T)、检查命令和渲染命令
cues.pytools/sound.py 使用的声音事件
finalize.py混音各音轨,合并到渲染视频,运行 tools/finish.py

通过复制 episodes/starter/toon 到 episodes/<name>/toon 来开始一个新剧集。 其 reel.py、build_tl.py 和 finalize.py 是通用的,可以保持原样;你需要替换 script.py、looks.py、scenes.py、SHOTS 表和 cues.py。不要从 episodes/window/toon 开始,它的 reel.py、cues.py 和检查逻辑是针对该故事定制的(两个镜像世界、命名标记、自定义反转镜头)。可以阅读它学习技巧:纹理、景深、每个世界的脸部关键帧、玻璃上的手、跨世界淡入淡出。较大的剧集应将表演逻辑从 scenes.py 移到单独的 acting.py 中。

一个世界需要两个方法:draw(fr, cam, T),绘制所有内容并返回 {pid: rig.draw 的结果};以及 cast(T),返回 [(pid, look, pose)]。pid 是剧集中的角色 ID(例如 "nora")。每个地点一个世界和一个时间线;镜头只选择摄像机。

4. 造型(references/look.md)

圆润简单的形状,头部稍大,大眼睛富有表现力,哑光材质,带柔和的 3 级渐变阴影,以及比底色更深的外轮廓线。每个角色根据剧本拥有自己的剪影、面部和配色设计(绝不能对另一个短片的角色进行换皮);重复出现的角色保持造型一致。在动画制作前,从 tools/toon 运行 python -m cast.sheet ../../episodes/<name>/toon/looks.py <look> 制作造型表(它会在项目根目录生成 assets/kit/cast/<look>.png,或者你指定的第三个参数路径)。

5. 布光(references/lighting.md)

每个场景都有三层:冷色环境光(蓝紫色夜晚能保留细节),每个面部的柔光主光(从上前方来,由台灯或窗户激发),以及暖色实用光源(分布在几个距离上,照亮它们附近的东西)。面部是画面中最清晰的部分;背景在面部周围稍暗且对比度稍低。脚底、家具和接触的手部有接触阴影。每个地点一个灯光方案:方向、颜色和曝光在剪辑间保持一致。没有发光效果、没有发光轮廓、没有纯黑区域。当故事中有天气时,在安静时刻动画化天气(雨、雪、风)。

6. 摄像机(references/camera.md)

  • 每 2-3 秒一个切。每个镜头服务于一个动作、一个表情或一个揭示。
  • 钩子(0-3 秒)是短片中最漂亮的运动镜头:从第一帧起摄像机和角色就开始运动。
  • 先全景双人镜头,然后匹配的单人特写。特写镜头保持在视线方向约 35 度范围内。
  • track(a, b, ease) 在两个关键帧 (position, target, focal px, horizon) 之间进行一次干净的运动。摄像机会转向面对目标,但不能倾斜:目标的纵轴高度会被忽略。通过调节摄像机高度和 horizon 值(较小的值使视线在画面中更高,看起来像是向下看)来上下构图。
  • 保持摄像机与画面中任何人的距离 >= 0.45 米:rig.draw 不会绘制比这更近的人。
  • 字幕(Arial Black 66px,白色,黑色描边,关键词 #FF4D4D)绝不能出现在脸部或手上。使用 cap=(y, size) 为每个镜头移动字幕位置。

7. 表演与舞台调度(references/acting-staging.md)

每个动作都是带有偏移量的链条:眼睛 -> 头部 -> 肩膀 -> 身体 -> 手,按照预备 -> 动作 -> 稳定结束的顺序。反应使用缓出/突然停止,稳定结束使用缓回。抓取动作在手掌合拢之前先行靠近。一个只转动头部和肩膀的角色可以站在默认脚位上;一个需要行走或转动身体的角色,其双脚必须固定在世界空间坐标中(使用来自 rig.replant 或 rig.gait 的 ankle_R/ankle_L),一次迈出一步。在封锁任何表演之前,请阅读舞台调度故障清单:每一个都是已经发生过的错误。

8. 检查:每次主渲染之前的关口(references/checks.md)

  1. python reel.py --check -> 读取整个 review/reel_checks.txt。在模板示例中,每个问题都是 ANOMALY 行:伸臂问题、脚部陷入地面、肘部过度弯曲、肘部和膝盖翻转、抖动、人物离镜头太近、字幕遮挡脸或手。
  2. python reel.py --stills -> 每个镜头的第一/中/最后一帧(第一轮检查)。
  3. python reel.py --sheet <SHOTS> -> 每一帧 的接触镜头、行走、转身和遮挡变化,以分帧图形式输出(第二轮检查)。检查分离、肢体弹出、头部穿过物体、物体消失等问题。
  4. 在数据中修复后重新运行,并在 review/LOG.md 中记录每条异常(只追加写入):时间、镜头、原因、修复方式、验证方式;以及接受标记(附理由)和无法检查的部分。
  5. 绝不能仅凭代码就声明“无异常”。代码检查的是关节而不是画面:它无法看到人物穿过家具或彼此、道具没有握在手中、错误的绘制顺序、或一个 0.8 米的侧向步幅看起来像劈叉。这些需要你在分帧图上自己发现。

9. 渲染(从剧集文件夹)

  • python reel.py --preview --full -> review/reel_preview.mp4(1080x1920,无声)。python finalize.py preview 添加混音 -> review/preview.mp4。展示给用户,获得批准。
  • python reel.py --master-par 12 -> video/reel_silent.mp4:使用 12 个进程的主渲染(根据你的核心数调整)。

10. 音效、混音、导出、后期处理(references/sound-finish.md)

  • cues.py,然后从项目根目录运行 python tools/sound.py episodes/<name>/toon -> 生成音乐、音效和氛围音轨。真实物体使用真实录音(将 CC0 或已授权样本放入 assets/sfx/);只有抽象的嗡嗡声、上升音和爆音才使用合成音。模板示例的提示音全部是合成的以便流程运行:请替换它们。
  • python tools/mix_check.py episodes/<name>/toon:人声在任何一句台词上必须比背景音高 >= 10dB(在有人声录音之前每一句都会失败)。
  • python finalize.py final(在剧集文件夹中运行) -> tools/finish.py -> -14 LUFS,<= -2 dBTP,H.264 High,+faststart。
  • 封面图,从项目根目录运行:python tools/thumb.py frame.png cover.jpg --line "TITLE:#F2EFE6:120"。
  • POST.md:各平台的字幕、话题标签,以及提醒在应用中开启高清上传。

本文使用的术语

  • mark:一个以秒为单位命名的故事节拍(在 MARKS 中),用作镜头边界和动作的计时依据。
  • station:角色站立的位置(x, z,朝向)以及他们走到该位置的时间。
  • planted foot:在世界坐标中固定了一个脚踝位置(ankle_R/ankle_L),使脚不会滑动。
  • clip zone:屏幕空间裁剪区域,用于隐藏身体的一部分(如树篱、墙边)。
  • wall-flat item:挂在墙上的平面布景(窗帘、海报);将其排序到墙的最远层。
  • practical:场景中可见的光源(台灯、亮着的窗户)。

工作习惯

  • 先看再断言。渲染画面,读取分帧图,然后说出你看到的。
  • 一次更改,一次受影响镜头的重新渲染,一次重新检查,并附上分帧图。
  • 当某个舞台调度反复失败时,简化它或选择一个更清晰的角度。绝不能依靠模糊、黑暗、剪辑或字幕来掩盖问题。
  • 将用户的每一条修正意见写入剧集的 review/LOG.md 中;如果是通用性的,写入项目根目录的 STAGING_NOTES.md(在每集开始时阅读)。绝不能写入插件自己的文件夹中。

相关技能