卡通短片:创意 → 脚本 → 配音 → 成品MP4
视觉风格:平面2D豆形头卡通角色(类似手绘的“卡片”风格,带有李子色轮廓)在色彩丰富的3D世界中,具有黑色墨水轮廓、手绘纹理、景深和滑动摄像机。输出为1080x1920,30帧/秒,时长与配音完全一致。用户配音保持不变。音乐背景和音效为合成,电平设定为配音电平的50%。已验证于作品“从未离开的士兵”(19.7秒,8个镜头)。
规则
- 故事、角色和镜头始终原创。不得逐镜头复制其他创作者的作品。应提供相同创意的原创演绎。
- 不得使用真实、知名的在世人名作为角色,也不得使用品牌吉祥物或标志。
- 除非用户要求,不添加字幕。剧情内文本(如雕刻的信息、标志)可以,且必须正确显示(不能镜像)。
- 不得编辑或重新调整配音的时间。画面与配音同步,每个视觉反应应在对应词语前0-3帧出现。
- 音频电平: 音乐背景电平为配音电平的50%(−6 dB,门控RMS)。音效应为50%或略低,峰值受限,确保任何撞击音不突出于旁白之上。始终使用
mix.py进行混音,不得手工调整。不得使用会改变此比率的闪避或压缩;整个混音仅允许一次线性增益加一个峰值限制器。 - 通过任务列表告知用户进度。在长时间渲染前发送关键帧联系表。
第一阶段:输入(始终首先执行)
如果已附加音频文件,直接跳到阶段4。如果也提供了脚本,则用于计时。否则询问一个AskUserQuestion(如果该工具缺失则使用纯文本):"您从哪一步开始?"
- 配音已准备好:要求用户上传配音,以及脚本文本(如果有的话,脚本可使计时更精确)。上传后进入阶段4。
- 我有脚本,需要配音:根据需要按阶段3精简脚本,返回脚本并附上录音提示,要求上传,然后进入阶段4。
- 需要视频创意和脚本:进入阶段2。同时询问目标时长(如果用户未说明)。默认20-30秒;允许45-60秒。
第二阶段:10个视频创意
在一个回复中提供恰好10个创意,编号,并要求用户回复一个数字(或"更多")。每个创意包括:
- 标题(5-8个词,引发好奇心,例如"从未离开的士兵")
- 钩子句:第一句口语,以事实陈述的悖论("一个人卖掉了埃菲尔铁塔。两次。")
- 转折(一行,视频结尾的讽刺性收尾)
- 为何适合动画化:2-3个重要的视觉时刻(如坍塌、揭示、追逐)
- 真实或传说:明确说明是记载的历史、有争议的记载还是民间传说
什么创意对于此格式"完美":
- 一个令人惊讶的故事,具有可展示的物理因果关系。
- 一个清晰的普通角色,逐步升级的赌注,以及最后一行的转折。
- 一个可以用简单3D形状加卡通卡片构建的场景(城镇、桥梁、船只、城堡、沙漠、实验室、宫殿)。
- 10个创意跨越时代和主题:古代、中世纪、1800年代、现代、科学、动物、发明、灾难、奇怪法律、幸运意外。
- 对于任何作为真实呈现的内容,先通过网页搜索验证关键事实。不要将病毒式传说呈现为事实。如果用户仍想要,应表述为"传说称"。
- 不以真实在世人作为笑话对象,不涉及血腥或政治内容。
第三阶段:脚本(用户选定后)
仅撰写旁白(口语文本中不含舞台指示),语速约3.7词/秒:20秒≈75词,30秒≈110词,60秒≈220词。公式:
- 钩子(第一句,无需铺垫):荒谬的事实。
- 背景(1-2行):时间、地点、人物、具体细节。
- 升级(2-4个节拍,每个更大的节拍)。他人怀疑或嘲笑。使用一个夸张笑话。
- 谜团或转折:"但当时……" / "你看," 引入真正的机制,通常用日常类比。
- 转折/收尾:简短、讽刺,视频的最后几个词。使用简单的英语口语,缩略形式,句子长约8-15词,数字用文字写出。切勿描述观众已经看到的内容。
然后回复:
- 可复制的脚本块,包含字数统计和预估时长。
- 一段视觉计划(将要动画化的镜头)。
- 录音提示:一个稳定、温暖的叙述声音;ElevenLabs效果良好(深沉叙述声,速度约1.05-1.1,稳定性约45-55%)。Mp3或wav格式均可。在句子结尾留自然停顿。导出时不带音乐。
- 要求:"配音准备好后请上传,我将制作完整视频。" 保留最终脚本文本。它将驱动阶段4的计时,因此无需语音识别。如果用户录制了更改后的版本,请要求最终文本。
第四阶段:制作视频(配音上传后)
从此处开始不间断执行所有操作。仅在计时无法解决时提问。
4.0 获取工具包
代码工具包位于本技能文件夹内的kit/(引擎、工具、工作示例,以及来自github.com/mromidev/claude-animated-shorts的三方库three.js r160和toon.ts笔库,均为MIT许可证)。使用find / -name SKILL.md -path "*cartoon-audio-short*" 2>/dev/null定位文件夹,并将其kit/视为只读。
然后运行bash <技能>/kit/tools/setup.sh ~/shorts/<slug>。它将引擎和工具复制到项目中,安装三方库three.js,用Node 22的module.stripTypeScriptTypes从toon.ts中移除类型,并链接Playwright。无需网络。如果三方文件缺失,则回退到npm或git克隆。
- 要求:Node 22.6+,带numpy和Pillow的Python 3,ffmpeg,以及带Chromium的Playwright(如果缺失则运行
npm i -g playwright && npx playwright install chromium)。 - 如果包注册表被阻止,Git over GitHub通常有效。切勿禁用TLS或绕过代理。
- Chromium:使用预装的Playwright浏览器,并带
--use-angle=swiftshader --enable-unsafe-swiftshader --ignore-gpu-blocklist参数。这将提供CPU WebGL,每帧约3-10秒。
4.1 计时
运行python3 timing.py voice.mp3 script.txt --out work。
- 如果安装了whisper或faster-whisper,则使用词时间戳。
- 否则,它将脚本短语(按标点分割)与静音检测的语音片段对齐,使用DP(动态规划)匹配音节与时长,并惩罚片段内句子结尾和短语内长间隔。
- 如果没有ASR和脚本,请要求提供脚本。Claude无法听到音频。
- 检查
work/phrases.json:停顿应出现在句子结尾。总帧数 = round(时长 × 30)。
4.2 镜头计划(代码前的work/PLAN.md)
每行一个镜头:帧数、词语、场景、灯光、相机运动、角色/姿势/表情、效果和音效提示。
- 第0帧已经是钩子图像。
- 通常每个短语一个镜头。将很小的短语合并到下一个镜头。
- 按字面意思说明每个句子。道具承载笑话。
- 变化镜头景别:钩子中景 → 宽景揭示 → 双人镜头 → 关键物体插入特写 → 反应特写 → 收尾的环境运动。
- 使用灯光表示节拍:白天表示正常,金色表示衰落或戏剧性,夜晚蓝色表示解释。时间跳跃使用6帧白色闪白。
- 转折行使用刺音(音乐停止,低音重击,推镜头并旋转)。最后一个镜头的物理收尾落在最后一个词上。
4.3 世界(web/main.js)
保留引擎部分:toon材质、墨水收缩、add/tbox、天空、灯光、卡片、渲染目标/后处理、applyLight、drawActors、swapForNd、renderFrame。替换// ---------- world ----------和// ---------- cards ----------之间的示例世界,以及worldState()的故事部分。
- 使用基本几何体配合绘制的画布纹理(
paint.js:木板、横梁、朽木、石头、苔藓/常春藤、草、泥土、灰泥、屋顶瓦片、大理石、横幅、雕刻文字)。编写新的绘图器时保持平坦带深色缝隙的风格。 - 使用
tbox实现恒定纹素密度,两步toon渐变色,以及雾 = 地平线颜色。 - 背景:山丘(半掩埋的球体)、山脉(圆锥 + 雪顶)、柏树/松树、远处的房屋、绘制的云朵广告牌。
- 场景道具(坍塌、下落、门)是由
worldAt(f)驱动的0..1进度控制的枢轴组,带有缓动和交错部分。 - 弯曲的剧情内文本使用平面UV。检查是否镜像。
4.4 角色(web/roman.js → web/toon.js)
romanFront(p, outfitKey, opts)在600x1000的设计画布上绘制,鞋底在y=975处。卡片高2.25米,因此1单位 = 0.00225米。- 向
OUTFITS添加服装(束腰外衣/斗篷/盔甲/头盔/头发/帽子/胡须/围裙/连衣裙/托加袍)以及相同风格的新头饰和道具。 - 手臂姿势:下垂、持矛、指、举、挥手、叉腰、腹部、太阳穴(+漩涡)、抬、够(+抬)、脸颊、盾牌、交叉、拇指。
- 表情:toon.ts的FACE集外加打鼾、固执、眯眼。扩展FACE以增加更多。
- 编辑后通过命令
cat web/toonbase.js web/roman.js > web/toon.js重建。在使用新设计前渲染角色测试页。 - 广告牌仅偏航旋转,具有接触斑点和alpha测试阴影,不被世界通道墨线勾勒。
- 从
q()舍入值构建卡片键(因此画布仅在可见变化时重绘)。 - 分离的部分(例如举起的头盔)是单独的卡片,与
headCenter(seed)对齐:y = DECK + (partY − hc) × 0.00225。
4.5 运动:流畅且生动(web/motion.js)
- 相机:
camFromKeys(keys, f, {kicks})。使用更平滑的步进滑动(18-45帧),easeOut用于揭示和甩镜头,以及path通过点(Catmull-Rom)用于曲线运动。每个保持都有微小运动,无静止超过4帧。在戏剧性场景中使用3-5°旋转,在撞击中使用7帧翻转抖动。 - 连续性:偏好连续运动(从特写拉回成远景,推拉对焦,通过甲板移动起重机,推近物体)。仅在地点或时间跳跃时使用硬切,并配以闪白。
- 角色永不冻结:对每个卡片应用
idle(f, seed),blinkAt眨眼,在重读词上点头。 - 动作:预期 →
back过冲 →spring稳定。跺脚是2帧下沉 + 灰尘团 + 踢。大笑是交替倾斜 + 点头。 - 次要运动:旗帜布波动、树叶/灰尘/水滴/Zzz效果卡片、流水。总有东西在动。
- 行走:
walk()给出距离 + 步幅相位。脚部着地,上下摆动3-7%。 - 镜头:景深用于特写和中景(cInf 8-14像素),对焦在眼睛。广角清晰。推拉对焦约需14帧。
4.6 视觉检查(完整渲染前)
在每个镜头的中间帧以及转场和关键动作处渲染静态帧:node render.mjs stills/a "5,40,..." 然后 python3 sheet.py stills/a stills/sheet_a.jpg。查看图板并修复以下陷阱:
- 窄垂直帧:水平半宽 = d·tan(hfov/2),其中hfov = 2·atan(tan(vfov/2)·0.5625)。在4米和fov 40时,此值为±0.8米,因此角色需要纵深站位。
- 栏杆或柱子遮挡面部(相机在栏杆内或约2.5米高)。相机路径穿过房屋、屋顶或灌木丛。前景道具距离小于约2米。主角被柱子遮挡。
- 镜像文本。分离部分卡片偏移错误方向。
- 挤出材质组:0 = 端盖,1 = 侧面+顶部。
- 缺少墨水轮廓:调试仅边缘输出。墨水半径约2.5像素(1080分辨率)。天空算作远距离,不是卡片。将图板发送给用户,附带一行镜头摘要,然后开始完整渲染。
4.7 声音(audio.py → 分轨 → mix.py)
为故事重写提示表;合成器保持不变。audio.py仅写入分轨(music.wav,sfx.wav)。
- 音乐:一个短的行进风格循环(底鼓/军鼓、弹拨贝斯、铜管垫音)。在转折行处停止,然后一个低音持续音继续。
- 音效基于事件(以帧/30为单位):大动作时的嗖嗖声、跺脚时的重击声、坍塌时的隆隆声和破碎声、金属刮擦声、揭示时的叮当声、转折时的刺音、吱吱声、噼啪声、水花声、鼾声、树叶声、水环境音。
- 使用
python3 mix.py voice.mp3 music.wav sfx.wav混音。它将音乐电平精确设置为配音门控RMS的50%(−6 dB),音效为50%,峰值限制在配音峰值的0.7倍。它会打印测量的电平:确认音乐显示为−6.0 dB相对于配音,音效等于或低于该值。 - 在制作声音前锁定画面时间。任何时间变化都需要重新运行audio.py和mix.py。
4.8 渲染 + 完成
- 使用Bash的
run_in_background运行node render.mjs frames "0-<N-1>",由Monitor循环监控,报告进度并捕获错误或进程退出。RESUME=1可在中断后继续。小型机器上不要同时运行繁重的Python任务。 - 运行
bash finish.sh "Title"。它应用一个线性增益到约−14 LUFS并加−1 dBFS峰值限制器,编码H.264 CRF 17 + AAC,运行冻结/黑屏和响度检查,并写入out/qa_sheet.jpg。查看图板。冻结持续时间≥0.4秒或黑帧需要修复。 - 使用SendUserFile交付MP4,并附带几行说明每个镜头显示的内容。提供字幕、调整或列表中的下一个创意。
引擎注意事项(保留在工具包中;如重建则保留)
#include <fog_vertex>/<fog_fragment>应独占一行。- 最终通道写入
linearToOutputTexel(...)(渲染目标为线性HalfFloat)。 - 正常+深度通道按网格交换材质:世界 → 正常/深度,卡片 → alpha测试遮罩(rgb 0,a = 深度),斑块/云/天空隐藏,水 → 平面法线。在此期间禁用雾和阴影。
- 墨水轮廓仅应用于深度跳跃的近侧。折痕来自法线点积。跳过相邻卡片。墨水轮廓在约140-520米处淡出。
- 景深:48个采样点,带逐个采样点的CoC测试(无前景扩散)。
- 根据光照预设的方位角/仰角确定太阳位置。阴影相机以每个镜头的动作为中心。
架构(用于编辑工具包的参考)
web/index.html通过本地HTTP服务器加载main.js(ES模块)