Communitygithub.com

手绘水彩墨动画技能

用代码制作手绘水彩墨风格卡通视频(MP4)——基于 p5.js + p5.brush,在无头 Chrome 中逐帧渲染,通过 ffmpeg 编码,主角为 Clawd 或任何角色。

手绘水彩墨动画技能 是什么?

该技能将传统手绘动画工艺转化为代码工作流,为开发者提供了一套完整的管线来创作水彩墨风格卡通短片。它基于 JohnHeibel 的 PDoomVideo 和 ClaudeAnimationBase 项目,核心思想是将每一帧定义为纯时间函数,利用 p5.js 和 p5.brush 库模拟水彩填充和墨水线条的视觉效果。工作流涵盖从项目脚手架、故事板编写、逐镜头实现到最终渲染的全过程,支持图像联系表预览和本地/云端两种渲染模式。特别针对音乐视频场景提供了歌词 LRC 同步、节奏自动分析等功能。技能严格遵守“手绘媒介”美学规范:仅使用 paint()/inkLine() 进行绘制,禁止纯 p5 图形;每帧必须包含事件推进、角色情感变化和镜头过渡;角色始终保持“活着”的动态感。并行渲染架构和缓存机制使长视频生成变得可行,但开发者在云环境中渲染前需注意成本与时间。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Joker-chichi/claude-mv-skill/tree/HEAD/skills/painted-animation

在你喜欢的 AI 中提问

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

文档

手绘动画

一种完全用代码制作短片的创作方法,源自 JohnHeibel/PDoomVideo(一部由 Claude Opus 绘制的 156 秒音乐视频)及其通用工具包 ClaudeAnimationBase(MIT 协议),该项目已作为 template/ 包含在此。

工作原理: 每一帧都是时间 t 的纯函数。studio.html 加载 p5.js + p5.brush 和您的场景文件;每个镜头使用水彩填充和沸腾墨线绘制完整的 1920×1080 帧。render.mjs 驱动无头 Chrome 生成联系表以供预览,或并行渲染所有帧,然后由 ffmpeg 编码为 MP4(如果提供音频则包含声音)。

工作流程

0. 项目脚手架

bash ~/.claude/skills/painted-animation/scripts/new_project.sh <项目目录>        # 添加 --keep-demo 可保留示例场景

此命令复制模板,断开演示场景,运行 npm install 并检查 node / ffmpeg / Chrome。然后,在设计任何内容之前完整阅读 <项目目录>/ANIMATION_GUIDE.md:其中包含规则、动画原理以及完整的引擎/Clawd API。使用读取工具查看 docs/emotions.jpg 和 docs/views.jpg(角色模型表)。

对于音乐视频或任何时长超过约 20 秒的作品,还需阅读 references/music-video.md。

对于每个音乐视频,在开始故事板创作或场景实现之前,请完成以下信息收集:

  1. 请用户同时提供歌曲音频文件及其 .lrc 歌词文件。当需要 LRC 时,不要自行编造、转写或近似缺失的歌词。
  2. 务必询问创作方向,即使用户已经提及部分内容。请将其作为一条自然语言消息中的一个问题提出,涵盖预期的故事、整体感觉以及任何要包含的反复出现的视觉想法或要避免的内容。不要将其拆分为多个问题、字段、清单或五个部分的表格。告知用户可以用一句话回答,也可以留空。例如:“这部 MV 应该讲述什么样的故事和传递什么样的整体感觉?有没有你想包含的反复出现的画面,或者任何你想避免的内容?如果你没有偏好,可以留空。”
  3. 确认收到的文件,并根据单个答案推断的创作方向进行总结。在内部提取故事、情感、氛围/意象、视觉主题和需避免的内容;不要要求用户分别回答这五个类别。将空白答案视为“无偏好”,而非缺失输入,并在故事板创作时提出合适的解读。如果音频或 LRC 文件缺失,暂停音乐视频工作流程并请求提供。
  4. 使用 scripts/beat_grid.py 测量节奏;歌词行的节奏通常比您想象的要快。将提供的音频和 LRC 作为时间依据。

1. 先写故事板,后写代码

在项目中编写 STORYBOARD.md(格式见指南:故事梗概、世界+调色板弧线、主题、角色情感弧线,然后是与理解要点并列的镜头——观众必须理解的时间化列表)。示例:examples/xiaozhen/(一个 31 秒的歌词视频:故事板和完整场景代码)。

对于音乐视频,请将用户的故事和情绪转化为连贯的视觉叙事和情感弧线,而不是逐字逐句地诠释每条歌词。在动手制作前,向用户展示故事板并让他们做出反应——除非他们表示可以直接进行。

2. 逐镜头构建

  • 在 src/config.js 中设置 duration、bpm、offset(以及 audio)。
  • 每个场景/章节一个文件,放在 src/scenes/ 中,使用 IIFE 包裹,以 shots([[t0, fn], ...]) 结尾;将其 <script> 标签添加到 studio.html。
  • 首先确定关键姿势,以静态图片形式检查它们,然后添加它们之间的动作。

3. 渲染与审视——每个镜头,多次

无法通过阅读代码看到动态效果。在项目目录中运行:

node render.mjs --sheet=0.1,0.8,1.6,2.4 --cols=4 --w=480 --out=out/check/a.jpg        # 关键帧
node render.mjs --strip=2.1:2.6 --out=out/check/strip.jpg                             # 某一时刻的每一帧
node render.mjs --sheet=2.3 --crop=760,420,500,400 --w=500 --out=out/check/face.jpg   # 全分辨率细节

使用读取工具打开每张图片,并根据指南的检查清单进行实际检查:事件清晰吗?角色足够大吗?理解点的时间安排是否让首次观看的观众能够理解?有预期动作/动作延续、无突变吗?脚部和手持道具接触地面吗?每个接缝处都有过渡吗?没有文字、3D、纯黑/白、浑浊的光晕吗?修复后再次查看。预算:每个镜头至少一张联系表,每个关键动作和过渡一张条带,每个承载叙事的脸部一个裁切区域。

联系表、静态帧、短条带以及其他少量帧的预览可以在当前云环境中渲染和查看。请特意将这些预览渲染做得小巧且有针对性地服务于视觉验证,不能替代整个视频的渲染。

4. 渲染最终视频

切勿直接开始完整渲染。在预览审查完成后,告知用户完整的云端渲染可能非常缓慢,并明确询问他们希望最终视频在本地还是云端渲染。等待他们的回答;故事板批准、预览批准或之前的一般性指示都不构成渲染授权。

  • 如果用户选择本地渲染,则禁止在云端进行完整渲染。除非用户之后明确改变选择,否则不要在云端启动完整序列。完成已验证的项目文件,询问(如果未知)用户的操作系统,并提供该平台的确切前提条件、npm install、帧渲染和编码命令。保留预览图片,以便用户知道已批准的内容。
  • 如果用户选择云端渲染,确认预期的时长、帧数和可能的成本/时间,然后继续进行可恢复的多工作者渲染。
  • 如果用户未回答或给出模糊的答案,不要运行完整渲染。再次明确询问本地或云端的选择。
node render.mjs --clip --out=out/video.mp4                                   # 短视频,一个工作者
node render.mjs --frames --workers=4 && node render.mjs --encode --out=out/video.mp4 [--audio=assets/song.mp3]   # 长视频,并行+可恢复

报告输出路径、时长和每帧毫秒数。提供 open out/video.mp4。

最重要的规则

以下是指南规则的浓缩版;指南具有权威性。

  1. 手绘媒介。 只能使用 paint() / inkLine()(p5.brush)——绝不能使用普通的 p5 的 rect/ellipse/fill。仅限平面 2D:角色转向通过绘制关键视图实现(turn()、spinView()),从不使用 3D 投影。光照通过 glow()(加法混合)实现,因为颜料混合会使黄色覆盖蓝色变成绿色。
  2. 无文字。 没有字幕、标签、标牌或对话气泡;用画面来表现。角色反应通过绘制表情符号(!、汗滴、爱心等)来实现。唯一的例外是歌词视频中的卡拉 OK 字幕,以及最多几个大的音效文字。
  3. 每个镜头都有事件发生——一个事件、原因→结果、铺垫,并且要有回报。
  4. 给观众留出时间。 列出每个镜头的理解要点;一次只给一个理解点;动作要快,含义要停留;引导视线;理解点决定镜头长度。这是生成式动画最常失败的地方。
  5. 活起来。 没有静止的东西(通过 feel() 产生的空闲动作、漂移的摄像机、沸腾效果);面部通过 emotions() 变化,而非通过替换;角色要画得大(中景头部尺寸约 20–28,特写 40–70);所有事物都踩在节拍上。
  6. 每个接缝处都有过渡,并选择适合故事的过渡方式(笔刷擦拭、光圈/形状光圈、甩镜头、匹配剪辑、动作剪辑、摄像机跟随)。
  7. 一个整体。 一个世界、一条色彩弧线、一条情感线索、相互关联的场景、一个与开头呼应的结尾。

引擎注意事项

  • t 的纯函数。 帧是并行且无序渲染的:帧之间没有状态,没有 Math.random(),没有逐帧物理。使用 hash(i) 实现稳定的随机性,使用 jit() 实现沸腾效果。
  • 在每个独立的背景元素/道具之前 调用 boilSeed(key),否则一个移动的物体会导致它之后绘制的所有内容每帧都重新沸腾(抖动)。
  • 不要以 p5 的全局变量名命名全局变量。 p5 将 line、OVERLAY、text、color、scale……定义为全局变量;顶层 function line() 会失败并报 Cannot redefine property,导致页面永远无法准备就绪(渲染器超时)。将辅助函数保留在场景的 IIFE 内部,或为它们起不同的名称。
  • 门口、窗户和屏幕的图层顺序: 先绘制内部内容,然后在其上重新绘制周围的墙壁/框架,这样开口之外就看不到更宽的东西(例如火车的 inDoor + 门框、电视边框部件)。
  • 点列表中的 NaN 会抛出 Failed to construct 'OffscreenCanvas'——请保护退化几何图形。
  • 当摄像机缩放值 ≳ 2 时,大形状会丢失轮廓线;轮廓线宽度随缩放比例变化,因此在特写镜头中需要缩小 sw。
  • 成本 = 填充和描边的数量。 目标是 ≤ 约 1.5–2.5 秒/帧(日志会打印每帧毫秒数)。优先使用更少、更大的形状。在没有真正 GPU 的机器上,水彩填充会很慢——考虑减少 fill 形状,或者作为最后手段使用 --soft-gl。
  • macOS:渲染器使用 --use-angle=metal 并自动查找 /Applications/Google Chrome.app;否则通过 --chrome=<路径> 传入。

适配

  • Clawd 是默认主角,但并非必需。新的角色、道具和表情使用相同的工具(paint、ribbon、through、glow)绘制,并在所有镜头中保持一致性;新表情添加到 src/clawd.js 中的 EMO 对象里。
  • src/karaoke.js(模板)通过 core.js 中的 window.overlayHook 钩子为歌词视频添加逐字卡拉 OK 效果。
  • LOOPS.name = t => {...}; LOOPS.name.len = 4; + node render.mjs --loop=name --png 可为 GIF 生成无缝循环(ffmpeg -i out/loop_name/f%04d.png …)。
  • 更高的推理努力水平往往会产生更华丽、更详细的场景。

相关技能