Communitygithub.com

kbohara315/卡通3D短片

制作一段约 55–70 秒的竖版卡通故事短片,采用“色彩缤纷3D世界中的2D角色”风格,使用 three.js 和 Remotion 渲染。

卡通3D短片 是什么?

这是一个用于生成卡通3D短片的 AI 技能,由 kbohara315 开发,并在《为歌而垮的桥》(The Bridge That Fell for a Song,67 秒)中验证。它帮助用户创作历史/科学故事短片,角色是卡通平面卡片,背景是手绘风格的 3D 世界。技能通过 11 个步骤的管线工作:从选题、剧本撰写、配音、分镜规划、3D 世界构建、角色动画、后期合成,到音频制作和最终渲染。支持三个.js 和 Remotion 平台,输出 2K 竖版视频(1440×2560,30 fps)。核心风格包括:黑色墨水轮廓、饱和天空、景深背景、滑行镜头、语音旁白、合成音效和进行曲风格音乐。用户只需提供故事想法,AI 就能参考已建立的风格规则和视觉参数(如光照、景深、角色比例等)自动完成制作。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add kbohara315/animated-shorts-forge

在你喜欢的 AI 中提问

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

文档

卡通3D故事短片 (three.js + Remotion)

已验证示例:为歌而垮的桥。这是一段原创的 67 秒短片,讲述了 1831 年布劳顿桥和 74 名士兵齐步走过桥的故事。

  • 代码:所在 Remotion 项目的 src/videos/bridge/(合成 BridgeShort,1080x1920,30 fps)。
  • 脚本、配音和声音:~/bridge-short/。
  • 风格研究:references/。

风格参考来源于私下研究的频道 (references/: STYLE_BIBLE.md, reports/*.md, frames/)。

  • 这些视频是私下的学习资料。切勿上传、发布或发送。
  • 切勿抄袭其脚本、角色或镜头。故事、角色和配音必须是我们原创的。
  • 切勿在旁白或描述中提及该频道的名称。

用户规则适用:

  • 视频中不加字幕或标签。
  • 仅限英文。
  • 配音:语调平稳。
  • 笑点:基于真实研究的事实。
  • 标准混音:音乐 +3 dB,音效 -6 dB,语音不变。
  • 最终输出:2K 竖版 1440x2560,--scale 1.3333。
  • Opus max 验证每一步。
  • 每一步后保存。
  • 一旦脚本获批,就“直接执行”。

管线

  1. 主题和事实。 选取一个令人惊讶的真实故事,包含物理因果关系(最好是可视化的),并配一个简单的日常类比来解释它。
    • 在 SCRIPT.md 顶部写出事实及其来源。
  2. 脚本 (~3.7 words/s,55-70 秒)。遵循桥短片的节拍公式:
    • 钩子: 用一句话概括荒谬的事实(“74 名士兵只是走过一座铁桥,就把它震垮了。”)。
    • 设定: 年份、地点、自豪感。
    • 行动: 经过三到四个节拍的升级,每次升级规模略大。
    • 断裂: 摧毁的那一刻。
    • 冷面双行: “幸运的是……/不幸的是……”。
    • 解释: 通过一个日常类比(比如荡秋千的孩子)来解释一个物理概念。
    • 后果: 由此产生的规则。
    • 呼应转折: 结尾。
    • 永远不要描述观众已经看到的画面。
  3. 配音。 录制或生成 voice.wav,然后制作其单词时间戳 words.json(使用任何带单词时间戳的语音转文字工具)。
    • 将它们放在项目文件夹中,例如 ~/bridge-short/voice/。
    • 手动修正单词时间戳。所有内容都根据 words.json 进行计时。
  4. 镜头计划 在 story.ts 中:复制 templates/bridge/(最终的桥源码,与 Remotion 项目的 src/videos/bridge/ 相同)到 src/videos/<name>/,在 src/Root.tsx 中在 BridgeShort 旁边注册一个新的合成,并重命名。
    • SHOTS: id,a/b 帧,白天/金色光线,人群模式,tau 故事时间。
    • XFADE: 地点/时间变化处的交叉淡入淡出。
    • FLASH_AT: 钩子之后的白色闪光。
    • CAMS: 每镜头的键值 {f, dur?, cut?, s: f => {pos, look, fov, roll}}。
    • KICKS: 冲击翻转抖动。
    • DOF/dofAt: 每个节拍的镜头模糊。
    • FOREGROUND: 近景框道具。
    • 每个视觉反应安插在其对应单词前 0-3 帧。
  5. 世界。
    • lights.ts: 灯光和每个灯光下的 LOOK 天空/河流/云彩调色板。
    • shade.ts: 双色调阴影和 untone()。
    • build.ts: 城镇、房屋和 Kenney CC0 套件道具,重新着色,并带有视线剔除,移除任何遮挡摄像机的物体。
    • paint.ts: 使用 Canvas2D 绘制的纹理,接缝处涂成深色调。
    • world.ts: 天空着色器、雾(等于地平线颜色)、河流、每帧姿态、太阳在每个镜头中固定并相对于相机。
  6. 角色。
    • toon.ts: Canvas2D Pen 绘图 API,600x1000 设计画布,鞋底在 y=975,豆形头,棍状四肢,李子色可变宽度轮廓,面部库。
    • cast.ts: 面向相机的广告牌、人群、效果卡、眨眼、行走循环。所有广告牌放在 NOINK 层。
    • cardshade.ts: 卡片由场景光照明,无自发光。
  7. 后期 (Bridge.tsx + ink.ts + lensblur.ts + grade.ts)。
    • 合成器顺序:墨线 → 镜头预模糊 → 镜头主模糊 → 泛光 → NEUTRAL 色调映射 → 调色 (MSAA 4)。
    • 每个像素参数随输出高度 / 1920 缩放。
  8. 声音 (~/bridge-short/audio/: timeline.py, sfx_gen.py, sfx.py, music.py, instruments.py, dsp.py, mix.py)。
    • 事件表 → 合成的音效加上一段在语音下方闪避的原创配乐。
    • 输出:mix.wav (48 kHz, 精确长度),分轨和 cues.md。
    • 在制作声音之前锁定画面的时间常数。任何后续的时间更改都需要重新运行声音。
  9. 外观检查。 运行 node scripts/bridge-stills.mjs out/<name>/x_ 100,400 0.5。
    • 设置 BRIDGE_ENTRY=src/sandboxes/<n>/index.tsx 以渲染沙盒副本。
    • 使用 python scripts/sbs_sheet.py out.jpg --ours ... --ref ... 制作与参考帧的并排对比图。
    • 将它们发送给 Opus max 验证器:1-3 张图片,≤200 字的结论。
  10. 最终渲染。
    • npx remotion render src/index.ts <Comp> out/<name>/video.mp4 --codec h264 --crf 16 --scale 1.3333
    • 使用 -map 0:v:0 -map 1:a:0 混流(Remotion 写入静音音轨)。
    • QA: python scripts/short_qa.py final.mp4 out/<name>/qa shots.json 检查每一帧的黑帧、白帧、冻结帧和弹出帧,以及音量和片段。
    • 修复找到的任何问题,然后运行一次深度 Opus 审计。
  11. 交付。 将最终的 mp4 文件发送给用户,更新记忆,写笔记。

最终外观值(桥短片经过 4 轮验证器迭代后的值;全部在 templates/bridge/ 中)

每个新短片都从 templates/bridge/ 开始(复制到 src/videos/<name>/):外观存在于这些值中,故事存在于 story.ts / build.ts 布局 / cast.ts 角色中。Opus max 最终得分:色彩白天 7,金色 5-6,光照 5-6,墨线 6,纹理 5-6,角色 7,深度 6-7,构图 6-7(初始为 5/3/4/5/4/7/4/6)。

  • 灯光预设 (lights.ts,太阳相对于相机固定并冻结在每个镜头中):
    • 白天:方位角 75 / 仰角 48,受光面 [1.58,1.5,1.33],阴影面 [.30,.29,.36],提升 [.05,.06,.11](仅在阴影中有冷色调),天空顶部 #3e7fd2 → 地平线 #b8d0ec,雾 = 地平线颜色,25→300 m,uSat 1.08,超过 60 m 约 15% 蓝色雾霾。
    • 金色:方位角 6 / 仰角 7(逆光低太阳),主光接近 #FFB36B ×1.5,紫蓝色阴影(立面 ≈ #444380),天空 #ffc47c → #8a6f8a,仅超过 50 m 有桃色雾,太阳光晕 #ffcf9e + 泛光,接触光斑 + 真实卡片阴影。
  • 反射率 (paint.ts/build.ts):柔和的砖色/奶油色/赭色/赤陶色房屋,带有基座、檐口、窗台、窗罩、门阶、烟囱 + 烟囱帽,高度 7 / 8.4 / 9.8 m;暖灰/米色石材(饱和度比“故事书”风格低 −35%);赭色木甲板 C* ~51-58,接缝接近黑色;铁质部分深色且低饱和度。永远不要有柠檬色、薰衣草色照亮的面孔。
  • 墨线 (ink.ts):#030303,近处(6 m)5.1 像素 → 远处(90 m)3.3 像素,在 1080x1920 下,折痕从 35° 开始 ×0.8,深度跳跃 1%,仅远处雾色调 0.3;角色卡片在 NOINK 层(它们自带李子色墨线)。
  • 镜头 (lensblur.ts + story.ts 中的 dofAt):在 1080 下 cInf 像素:钩子/河流特写 15-16,近景 12-14,中景 10-12,公园 7,金色摇曳 5,广角/航拍 0。对焦在前排角色的眼睛上。
  • 后期 (Bridge.tsx):墨线 → 镜头预模糊 → 镜头主模糊 → 泛光(阈值 1.0,强度 .5,6 级,半径 .6)→ NEUTRAL 色调映射 → 调色;MSAA 4。胶片颗粒存在但已关闭(参考测量结果无颗粒;它会使文件大小翻两番)。
  • 角色 (toon.ts/cast.ts/cardshade.ts):豆形头高宽比 .94,李子色墨线 #241726,眼睛间距 .26 头宽,没有腮红,14 种表情;成年人 3.5 头高;行走上下弹动 5%,身体倾斜 1-7°,步幅 0.8 m;眨眼间隔 0.5-2.3 秒;紧贴脚底的接触阴影约 .5,白天有太阳方向尾迹;金色光线时仅内边缘发光(永远不是偏移的外部副本)。
  • 相机 (story.ts):大跳跃时硬切,18-40 帧平滑步进滑动,每次停顿都有微推(无超过 4 帧的静止停顿),撞击时衰减 7 帧的翻转抖动,4-4.6°的转动,约 1/3 的镜头有前景道具 (FOREGROUND)。

外观目标(根据参考测量;参见 references/reports/)

  • 墨线:
    • 世界线条:在 1080 宽时约 3 像素,接近黑色 #0b0a0c,几乎不随距离变化。仅轮廓、深度跳跃和法线折痕。墙壁/地板接缝或地平线上没有线条。角色卡片从不由世界墨线勾勒。
    • 角色墨线:深李子色 #201628-#2f1d28,在底部/阴影侧更粗。
  • 色彩:
    • 白天中值亮度 ~.57。非墨线第 5 百分位 ~.23(无黑色被裁切)。受光面彩度 C* 第 90 百分位 ~55。白天天空顶部 ~#5e93d9,地平线亮度 1.28 倍。
    • 金色:桃色地平线 #ffd08a,紫蓝色阴影(从不棕色),逆光太阳。
  • 深度:
    • 大约 1/3 的屏幕时间有景深(特写、中景、插入镜头),在 1080 下 cInf 10-16 像素,对焦在眼睛上。定场镜头和广角镜头保持清晰。
    • 雾 = 地平线颜色,白天 25→420 m,金色 20→360 m。
    • 泛光仅作用于 HDR 自发光物体:阈值 1.0。
  • 相机:
    • 大跳跃时硬切。其他所有镜头都是 18-40 帧的平滑步进滑动,在 720p 下峰值 ≤ 25 像素/帧。
    • 每次停顿推近速度为 0.15-0.35 %/帧,在关键单词处为 0.6 %/帧。
    • 转动角度 4-5°。
    • 没有手持晃动。冲击抖动每帧翻转符号,并在 7 帧内衰减。
  • 角色:
    • 大约 3.5 头高,腿部 1.4 头高。
    • 棍状四肢约 0.055 头宽,墨点手。
    • 豆形头(高宽比 ~0.93,更窄的下巴,更尖的头顶)。
    • 没有腮红或眼睛高光。脸部亮度 ~.93。
    • 行走上下弹动 3-7%,身体倾斜 1-7°,脚部着地。
    • 每 0.5-2.3 秒眨眼一次,持续 4 帧。

外观匹配循环(桥外观的达成过程;可用于任何“让它看起来像 X”的迭代)

  1. 先测量参考。 每个主题一个分析代理(运动、深度、纹理、角色、光照、轮廓、调色),每个代理将数字(而非形容词)写入 references/reports/<topic>.md。共享简报:compare/CONTEXT.md。报告是所有后续代理的事实依据。
  2. 沙盒,每个文件一个所有者。 将项目文件夹复制到 src/videos/<name>_{cam,world,mat,char,post},入口点为 src/sandboxes/<n>/index.tsx(与主项目的 index.tsx 相同,仅导入路径改变)。桥短片的所有权分配:
    • cam: story.ts (相机键值、剪辑、抖动、景深表、前景道具)
    • world: world.ts, lights.ts, shade.ts, grade.ts (太阳、天空、雾、河流、色彩、调色)
    • mat: paint.ts, build.ts (绘制纹理、建筑、道具)
    • char: toon.ts, cast.ts, cardshade.ts (角色绘制、姿势、卡片光照、特效卡片)
    • post: ink.ts, Bridge.tsx, lensblur.ts (轮廓通道、合成器、镜头模糊、泛光) 代理只能编辑自己沙盒中属于自己的文件,并用 BRIDGE_ENTRY=src/sandboxes/<n>/index.tsx node scripts/bridge-stills.mjs out/<name>/<n>/x_ <frames> 0.5 渲染静帧。
  3. 合并 使用 python scripts/bridge_merge.py [cam,world,mat,char,post](将主项目备份到 backup/bridge_<time>/,仅复制负责的文件)。然后运行 npx tsc --noEmit(过滤到项目文件夹),然后在下一轮之前从主项目重新同步每个沙盒(cp -f src/videos/<name>/* src/videos/<name>_<n>/)。
  4. 验证 使用一个新的 Opus max 代理:并排对照表 (python scripts/sbs_sheet.py out.jpg --ours a b --ref r1 r2),对每个区域按 10 分制打分(色彩白天/金色、光照、墨线、纹理、角色、深度、构图),并附带有帧编号的编号修复列表。将每个修复映射到文件所有者,并用 SendMessage 恢复该所有者的代理(保持其上下文)。桥短片得分:第 1 轮 5/3/4/5/4/7/4/6 → 第 2 轮 5/4/5/6/4/7/6/6 → 第 3 轮见笔记。
  5. 所有者之间的契约存在于导出的常量中(例如 ink.ts 中的 NOINK 层,story.ts 中的 dofAt/FOREGROUND,lights.ts 中的 LIGHTS/LOOK)。更改契约意味着要通知所有读取它的所有者。

注意事项

  • Kenney 自然套件材质是青色的:在 build.ts 中根据材质名称重新着色。
  • 相机最终可能会进入房屋内部:build.ts/world.ts 中的视线剔除器会移除任何遮挡相机光线的物体。
  • 如果与 DOF 在同一合并效果通道中,墨线会被覆盖。墨线必须在模糊之前有自己的通道。
  • 像素级的后期参数必须随分辨率缩放:静帧为 0.5 倍,最终为 1.333 倍。R3F 将 dpr 钳制到 ≥ 1,因此 --scale 0.5 的静帧仍然渲染 1080x1920 的缓冲区。
  • 磁盘: 每个 Remotion bundle 都会将 public/ (~1.3 GB) 复制到 临时文件夹\remotion-webpack-bundle-* 中,并且从不删除。在桥短片迭代过程中,60+ GB 填满了系统盘,导致渲染因 ENOSPC 而失败。始终使用 export TEMP='<大驱动器>/remotion-tmp' TMP='<大驱动器>/remotion-tmp' 进行渲染(bridge-stills.mjs 会自行设置),并在删除临时文件夹中的旧 bundle 文件夹之前询问用户(自动模式会阻止清理)。<大驱动器>/remotion-tmp 也会被填满(4 轮桥短片迭代后约 500 个文件夹 / 110 GB):当一个项目完成且没有渲染任务时,请删除其中的 remotion-webpack-bundle-* 和 puppeteer_dev_chrome_profile-* 文件夹。
  • 在 JS 字符串中,请使用 "<大驱动器>/remotion-tmp",切勿使用 "<大驱动器>\remotion-tmp"(\r 将变成回车符)。
  • Remotion 会写入静音音轨:使用 -map 0:v:0 -map 1:a:0 混流。
  • 在此环境中,子代理无法写入报告文件:要求它们提供一条 ≤150 字的最终消息,您自己将其保存到 out/<name>/<n>/REPORT.md。
  • out/ 内的临时 .ts 文件会破坏 tsc:请将它们命名为 .txt。
  • 2K 渲染运行速度约 4 fps(67 秒约 10 分钟)。0.5 倍的静帧在约 40 秒 bundle 后每帧需要 3-8 秒。
  • 2.5% 的胶片颗粒会使 2K 文件达到 910 MB 而不是约 250 MB,并且在 YouTube 上会变得模糊;参考素材中没有颗粒。请保持关闭。

验证器发现的易读性问题(检查每个新道具/镜头是否存在这些问题)

  • 如果秋千只画了一根绳子,并且消失在孩子身后,看起来像是上吊。 始终使用两根绳子连接一块宽木板,孩子坐在中间(toon.ts 中的 swingKid),并且框架的腿要避开摆动弧线(两端各一个 A 形框架)。
  • 距离镜头约 2 米以内的道具或漂浮物会变成巨大的、被裁切掉的模糊块。 当相机移动时,重新检查其新位置附近的每个道具(河流相机就移动到了漂浮的帽子中)。
  • 被画面边缘裁切的前景灌木看起来像一个“绿色球体”;前景道具必须可识别,否则就不放。
  • 旗帜: 红色 + 黄色星星/菱形看起来像越南国旗。请使用符合历史时期的旗帜(1831 年英格兰使用圣乔治十字旗)。

相关技能