Communitygithub.com

orange9angel/dula-flat-cel

使用图像模型和脚本制作平涂线稿动画短片,从故事、角色设计、绘图和口型变体到最终带有声音的视频。仅需 Python 和 ffmpeg。适用于动画短片、卡通风格、有限动画、对话类影片、保持角色跨镜头一致性,或修复口型不同步和绘图闪烁问题。

dula-flat-cel 是什么?

该技能提供了一套完整的工作流程,用于创建平涂风格的动画短片。它利用图像生成模型(如 Stable Diffusion)和一系列 Python 脚本,结合 FFmpeg 渲染,将故事、角色设计和口型同步音频整合为最终视频。其核心理念是“有限动画”,即每个绘图持续 3-4 帧,通过切换不同的绘图和口型来表现动作和对话,而非使用逐帧或 3D 动画。该工作流程专为简单的电视卡通风格设计,能有效保持角色在不同镜头间的一致性,并解决常见的动画问题,如口型不同步和绘图闪烁。它首先定义故事板和镜头配置,然后极其注重角色设计,通过 `paint.py` 脚本生成所有角色、背景和绘图。为了处理对话,脚本会为每个说话的角色创建局部口型变体,并通过 `prep_cels.py` 将绘图压缩为纯平色并锁定变体。最后,根据音频自动计算口型动作,并生成预览和最终视频。该技能主要面向能运行 Python 和 FFmpeg 的开发环境(如 Codex, Cursor),并提供了详细的检查清单以确保输出质量。

兼容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/orange9angel/dula-craft/tree/HEAD/skills/dula-flat-cel

在你喜欢的 AI 中提问

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

文档

平涂动画

单张绘图持续 3-4 帧,动画表现通过切换绘图和口型来实现。对于简单的电视卡通设计,这是能保持图像模型最一致性的路线。它既不需要 3D,也不需要视频模型。

脚本位于本技能的 scripts/ 文件夹中,路径相对于此 SKILL.md。下文用 $S 表示该文件夹。除 new_project.py 外,请在你的电影项目文件夹中运行它们。如果遇到环境问题,请使用 dula-start。

用对方的语言与他们交谈。

工作流程

python $S/new_project.py my_film && cd my_film

1. 故事与镜头

编写 story.md,然后编写 config/film.json(参见 film.json 参考)。第一个短片控制在 20-30 秒内,一句台词大约需要 2-3 秒,所以 15 秒可以容纳 3-5 句台词。仅使用原创角色。

对每一句台词,都要思考谁说、对谁说、以及镜头展示谁。笑话不应依赖于观众听不懂的词语。因果关系也需要绘图来表现(跑进来 → 抓住 → 物体飞走)。不要用切镜来跳过。

2. 角色设计(最重要的一步)

将每个角色放入 config/anchors.tsv 中(名称<TAB>外貌描述),然后运行:

python $S/paint.py anchors config/anchors.tsv

亲自打开并查看每张图片。 一些查看器会将透明区域显示为黑色背景上的彩色辉光,这看起来像失败的剪影。如有疑问,请检查步骤 3 中的 build/check_alpha.png。然后向对方展示设计并征得批准,然后再继续。之后的每一张绘图都基于这些设计,因此这里的错误代价最高。用语言描述来修正比例,例如“头部占身高的三分之一,圆脸,黑色小珠眼,红色工装裤”。

3. 背景与绘图

填写 config/plates.tsv(名称<TAB>描述)和 config/cels.tsv(绘图名称<TAB>角色<TAB>姿势)。绘图名称以角色名开头,如 hero_run_a。

python $S/paint.py plates config/plates.tsv
python $S/paint.py cels config/cels.tsv
python $S/prep_cels.py --bases-only    # 在绘制口型前检查 build/check_alpha.png 中的剪影

每张图片需要 1-3 分钟生成,paint.py 会报告进度。如果你的工具会终止长时间运行的命令,请在后台运行它。重新运行会跳过已完成的图片。要重做某张图片,请使用 --only <名称> --force。

要保持绘图和场景的连续性,可以添加一列命名要参考的图片:

hero_run_a	hero	向右跑,左脚在前。
hero_run_b	hero	向右跑,右脚在前。	hero_run_a
meadow	灰雨云下的草地。
meadow_sun	雨停了,阳光穿透云层。	meadow

规则:

  • 每张图片只绘制一个角色。角色设计始终是第一参考。切勿使用被拒绝的图片作为参考。
  • 首先决定角色的朝向。 逐张生成的图片各自选取方向,因此对话中的两个人很容易变成背对背。提前指定朝向,并使用 flip 来修正错误。
  • 动作循环中的每张绘图应参考前一张(上面的附加列),这样方向、比例和形状才能保持稳定。没有这个,循环就会产生跳跃感。
  • 要改变一天中的时间,重新绘制背景,并参考原始背景图。乘色无法隐藏蓝天。
  • 检查每个镜头中角色的比例。像“脖子向上伸长”这样的姿势描述可能会导致身体变形。

4. 口型与眨眼

每张说话的绘图都需要在同一图像上进行局部编辑。在 config/variants.tsv 中:

hero_stand_m1	hero_stand	仅将嘴巴改为半开的小椭圆。
hero_stand_m2	hero_stand	仅将嘴巴改为大张开。
hero_stand_blink	hero_stand	将双眼闭上为简单的曲线。不改动其他任何部分。

命名:<基础>_m1 为半开,<基础>_m2 为大张。如果只有 _m1,则嘴巴有两种状态:张开和闭合,这也有效。基础绘图本身必须嘴巴闭合。如果在绘制时嘴巴是张开的,则创建一个闭合变体,并在 film.json 中使用 talk 设置所有三种状态。

每个说话角色的每张绘图都需要自己的口型变体,包括行走循环中的每张绘图。

python $S/paint.py variants config/variants.tsv
python $S/prep_cels.py

prep_cels.py 将绘图压缩为真正的纯色,并将每个变体锁定到其基础图像。然后打开 build/check_alpha.png 并在品红色背景上检查剪影。重新绘制任何残留背景、缺失部分或眼睛被擦除的图像。如果它警告有较大的区域变化,则说明模型修改了身体。在 variants.tsv 的第 4 列添加一个窗口 x,y,w,h。

颜色在漂移? 你可以添加 config/palette.json(例如 {"skin": [250, 220, 190]}),使用从角色设计中采样的颜色。只有相近的颜色会吸附到它,并且 prep_cels.py 会在你修改后再次应用它。

5. 声音

选择一种方式:

  • 使用 dula-voice 生成语音,需使用对方自己的密钥。
  • 使用现有音频:将其放在 audio/voice/<台词ID>.wav,或在台词上设置 file。mp3 和 wav 都有效。
  • 制作无声草稿:为台词提供 seconds 值。

口型是根据此音频计算的,因此在制作测试片前要确定好语音。

可选:ambience(环境音)、bgm(背景音乐)、sfx(音效)和 songs(歌曲)。仅使用对方拥有使用权的素材。本项目不生成音乐。如果没有许可的音乐,就省去配乐,让环境音和音效来承载影片。

6. 测试

python $S/build_film.py
python $S/render.py --stills 1,3,5,8,12
python $S/render.py --range 0,20 -o output/pilot.mp4

当可见角色说话但嘴巴无法移动时,build_film.py 会报错停止,这是最容易遗漏的错误。在展示测试片之前,查看每一张静帧。 不要等到整部影片完成才展示给任何人。

让角色站到地面上:猜测 ground 值,渲染一张静帧,然后调整。这比计算快。

不要让镜头静止不动。除非某个节拍故意静止,否则给每个镜头安排一个动态元素:平移背景(pan)、使用 bob 或 shake、切换绘图、或者添加覆盖层(如下雨)。在最后一个镜头用 fade_out 结束影片。

7. 全片与最终检查

python $S/render.py
python $S/check_mouths.py

在交付前确认以下每一项,如果无法做到,请明确说明:

  • 你查看了每个镜头的一个真实帧
  • check_mouths.py 未报告冻结的口型
  • 每个角色在跨镜头时看起来仍然是同一个人(面部和比例比颜色更重要)
  • 对话中的人物彼此面向对方
  • 在屏幕上移动的单张绘图有 bob 或更多绘图,否则会看起来像是在滑动
  • 你听过了影片。如果你无法听,请说明音频未经耳朵检查

完整示例

本仓库中的 examples/rainy-slide 包含了一个 15 秒完成影片的提示词和镜头列表,docs/tutorial.md 对其进行了说明。从本文件路径可找到它们:../../examples/rainy-slide 和 ../../docs/tutorial.md。当有人要求看示例时,将它们作为模型使用。

节奏

经验法则:每个镜头平均持续 3-5 秒,每个绘图持续 3-4 帧(约每秒 7 个绘图),频繁使用特写和夸张表情。hold 是每个绘图持续的帧数。

常见问题

症状原因及修复方法
切换口型时身体颜色闪烁变体未通过 prep_cels.py
走路或跑步动画忽高忽低不要单独调整绘图大小。同一角色自动共享一个缩放比例。也可以加上 align_head
道具颜色错误调色板条目太接近。移除它或降低 SNAP 值
说话时嘴巴保持张开双状态口型使用 0.5 阈值。检查音频是否模糊不清
轻音词嘴巴闭合一个响亮的词设置了该行音量的比例。添加 _m2,或降低该行的 mouth_open_at
听不到雨声或风声环境音默认音量较低。为其设置 level_db,例如 -35
持续嘶嘶声环境音片段只是噪音。替换它。增益已封顶,因此不会进一步放大
Codex 报告参考图像丢失图像生成必须是它的第一个动作。paint.py 会处理此问题,所以请重新运行它

限制

此路线不适用于复杂的战斗、长时间连续动作或写实绘画。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能