Communitygithub.com

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

制作约55-70秒的竖版卡通故事短片,采用“3D世界中的2D角色”风格(平面豆形卡通角色配墨水轮廓、彩色3D小镇/世界配黑色墨线、饱和天空、景深背景、滑动摄像机、语音旁白、合成音效+进行曲风格音乐),使用 three.js 在 Remotion 中渲染。在《会唱歌的桥》(2026-10-31)中已证明有效。v2 版本新增逐字字幕、搞笑病毒式故事模板、构图/缩放/安全区规则、每个场景独立光照(室内、夜晚、日出)以及多样化的持续运动摄像机。

卡通3D故事短片(three.js + Remotion) 是什么?

这是一个为 AI 代理(如 Claude Code、Cursor、Codex)设计的专业技能,用于在 Remotion 中利用 three.js 制作优质的卡通 3D 风格竖版故事短片。它封装了一套完整的制作流程,从选题、编写病毒式脚本,到语音合成、逐字字幕、镜头规划、3D 场景构建、角色动画、后期合成及最终渲染。该技能包含严格的风格指南(如“2D角色在3D世界”)、构图规则(安全区、缩放限制)以及自动化的质量检查(构图、帧冻结、黑/白帧)。它支持多种场景光照预设(室内、夜晚、日出),并强调持续运动摄像机,通过命名移动和前景道具营造深度感。此技能适用于搞笑科学/历史事实短片或灾难故事,用户可通过类似“像那座桥的视频一样”或“使用卡通短片技能”的提示来触发。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/alifmahmudashik/shorts-studio-skill/tree/HEAD

在你喜欢的 AI 中提问

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

文档

卡通3D故事短片(three.js + Remotion) 是做什么的?

已验证示例:《会唱歌的桥》。这是一段关于 1831 年 Broughton 桥和 74 名齐步走士兵的原创 67 秒短片。

  • 代码:你 Remotion 项目中的 src/videos/bridge/(composition BridgeShort,1080x1920,30 fps)。
  • 脚本、语音和声音:~/bridge-short/。
  • 风格研究:references/。

风格参考是私下研究的频道(references/:STYLE_BIBLE.md、reports/*.md、frames/)。

  • 这些视频是私密学习材料。切勿上传、发布或发送。
  • 切勿复制其脚本、角色或镜头。故事、角色和语音必须是我们自己的。
  • 切勿在画外音或描述中提及该频道的名称。

适用用户规则:

  • 字幕:短视频默认开启。一次一词,居中,粗体,深色轮廓,位于安全区内,与 words.json 同步(参见“字幕”)。仅当用户要求时才关闭。没有其他屏幕标签。
  • 仅限英文。
  • 语音:一个稳定的语调(面无表情:叙述者从不反应,角色才反应)。
  • 笑话基于研究过的真实事实。
  • 标准混音:音乐 +3 dB,音效 -6 dB,语音不变。
  • 最终导出为 2K 竖版:1440x2560,--scale 1.3333。
  • Opus max 检查每项内容。
  • 每一步后保存。
  • 脚本一旦获批,就“放手去做”。

流水线

  1. 主题和事实。 选择一个令人惊讶的真实故事,包含物理因果关系(应该是可视化的),外加一个解释它的简单日常类比。
    • 将事实及其来源写在 SCRIPT.md 顶部。
  2. 脚本(约 3.7 词/秒,35-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 旁边注册一个新的 composition,并重命名它。
    • SHOTS:id、a/b 帧、光照 day/golden、人群模式、tau 故事时间。
    • XFADE:在地点/时间变化时的交叉淡入淡出。
    • FLASH_AT:钩子后的白色闪光。
    • CAMS:每个镜头的键 {f, dur?, cut?, s: f => {pos, look, fov, roll}}。
    • KICKS:冲击翻转抖动。
    • DOF/dofAt:每个节拍的镜头模糊。
    • FOREGROUND:近景构图道具。
    • 每个视觉反应在对应单词前 0-3 帧出现。
    • 将每个句子的主题连接成一个连续的流程(flow.ts,参见“连续流程”),给每个移动命名,每个停顿指定构图尺寸(参见“摄像机多样性”和“构图”)。
    • 给每个地点自己的光照预设(参见“每个地点的光照”)。
  5. 世界。
    • lights.ts:LIGHTS 加上每个光照的 LOOK 天空/河流/云彩调色板。
    • shade.ts:双色调着色和 untone()。
    • build.ts:城镇、房屋和 Kenney CC0 工具包道具,重新着色,带视线剔除任何遮挡摄像机的物体。
    • paint.ts:HD 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 词的评语。
    • 为每个镜头运行构图检查(templates/bridge/framing.ts),并制作一张包含每个镜头一帧(第一、中间、最后一帧)的接触表。参见“质量门”。
  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. 交付。 使用 SendUserFile 发送最终的 mp4,更新记忆,写下笔记。

预检(首先执行此项)

  • 检查 templates/bridge/、references/ 和 scripts/ 是否存在(如果缺失,请从 github.com/mromidev/claude-animated-shorts 或其分支克隆到 Remotion 项目旁边。如果它们缺失,请停止并获取它们。切勿在没有模板的情况下即兴制作一个通用的 three.js 外观。
  • 首先制作一个 15 秒的测试片段(钩子 + 2-3 个镜头,带字幕和声音)。渲染静帧,运行质量门,修复,然后扩展到完整的故事。切勿直接进行完整渲染。

病毒式故事格式:“嘲笑天才”(用于事实短片)

六个节拍,每次都遵循:

  1. 怪异动作 没有背景,显示在一张图片中(钩子,前 3 秒)。
  2. 笑声: 其他角色嘲笑英雄。
  3. 他们都看向右边: 时间流逝,英雄看起来错误或无害。
  4. 线索: 一个预示结局的细节。
  5. 结局: 证明英雄正确的事件(视觉高潮)。
  6. 科学: 展示机制(内部/剖面/微距视图)并用一句简单的话解释。
  • 将其作为有英雄的故事讲述,而不是事实列表。选择一个在一张图片中可见且人们会嘲笑的行为。
  • 最后一行开启一个论点或评论(有争议的内容),而不是一个简洁的总结。
  • 标题模式:“为什么 X……”、“如何 X……”、“X 的真正含义”。标题中不得剧透结局。
  • 节奏:每 2-3 秒一个新主题,通过摄像机移动到达(参见“连续流程”)而不是剪辑,在几乎每次移动或溶解(嗖、叮当、人群笑声)时都有音效,并且语音下有音乐。
  • 丰富的地点,简单的角色(圆头、火柴杆手臂):为一个 60 秒的短片规划 12-16 个不同的地点和 20+ 个道具,并给每个地点自己的光照氛围。
  • 首先写下事实及其来源。年份和数字以口语自然说出(“一八四七”),但字幕显示为数字。
  • 示例:templates/SCRIPT_viral_example.md。

让它变有趣(喜剧引擎)

人群嘲笑英雄;观众也应该笑。

  • 面无表情的旁白,荒谬的画面。 叙述者从不反应;角色才反应。两者之间的差距就是笑点。
  • 每 4-6 秒一个笑点,每个短片至少使用三种类型:台词笑点(轻描淡写,“幸运的是……/不幸的是……”)、视觉笑点(反应表情、背景中的小细节、错误比例的道具)和声音笑点(落在反应上的愚蠢音效)。
  • 三次原则: 两个正常节拍,然后第三个打破模式。
  • 贯穿全片的笑点: 一个背景角色或物体(鸽子、拿着三明治的人)出现 3-4 次,并在接近结局时得到回报。
  • 反应镜头: 摄像机停留在脸上(流程停止或变焦切换,不是剪辑)在重估词后 3-6 帧,并保持 8-12 帧。使用面部库;至少包含一个“不为所动”和一个“震惊”。参见“反应和对话节拍”。
  • 自信的英雄,自满的人群,过于严肃的官员: 角色极其严肃地对待琐碎的事情。
  • 仅为一个节拍夸张物理效果(结局):挤压和拉伸、灰尘云、冲击踢。
  • 回调结局: 最后一行利用所发生的事情反转第一行(钩子)。
  • 笑话保持在真实事实范围内:有趣的部分是真实的细节。切勿攻击真实受害者或群体;目标是过度自信和自满。

字幕(逐字字幕)

  • 来源:words.json(语音单词时间戳,手动修正)。任何语音转文本都可以;templates/bridge/Captions.tsx 中的 normalizeWords() 接受 {word|text, start|start_time, end|end_time}(秒或毫秒),并跳过 ElevenLabs 的“间距”条目。
  • 如果语音转文本的文字与脚本不同(数字、名称、拼写),则将文字替换为 SCRIPT 中的单词,并保留 STT 的时间。字幕显示脚本拼写(“1847”),即使语音说“eighteen forty-seven”。
  • 组件:将 templates/bridge/Captions.tsx 复制到 src/videos/<name>/,并渲染 <Captions words={WORDS} /> 作为 composition 的最后一个子元素,作为 three.js 画布上的 DOM 叠加层,位于后期处理合成器之外(文本上无墨水、模糊、绽放或调色)。
  • 样式:一次一词,水平居中,约在帧高度 68% 处(面部下方,安全区内),重型无衬线字体,白色填充,9 像素深色轮廓(基于 1080 宽度),弹出缩放 0.8 → 1.08 → 1 持续 6 帧,无背景框,最大宽度 86%。数字、名称和重估词使用强调色(highlight)。像素尺寸随输出高度 / 1920 缩放。
  • 切勿覆盖面部:当特写镜头中面部位于字幕位置时,传递 yPercent={(frame) => ...} 以移动该镜头的字幕。
  • 字幕在单词被听到前 1 帧出现(lead)。
  • QA:在每个镜头的一个重估词上渲染一帧静帧,确认字幕位于安全区内且不覆盖面部。

构图、安全区和缩放限制(强制执行)

  • 9:16 帧。安全区:左右 6% 边距,顶部 8%,底部 15%(平台 UI 和字幕)。所有重要元素(角色、道具、气泡、标志)完全位于其内部,故意的近景构图道具除外。
  • 角色头部最多占据帧高度的 30%(一次性反应笑点可使用 40%)。优先使用中景(腰部以上)和全身远景。
  • 切勿在脚部裁切角色,也切勿裁切对话气泡或标志。前景道具要么可识别,要么消失;被裁切的道具不得覆盖超过 35% 的帧。
  • 连续两个镜头不得具有相同尺寸(远景 / 中景 / 特写 / 插入)。
  • 保持静止时的推入速度缓慢:每帧 0.15-0.35%,重估词时为 0.6%。无突然的大缩放。
  • 自动检查:templates/bridge/framing.ts 中的 checkShot(camera, items) 将边界框投影到屏幕空间并列出每个问题。在每个镜头的第一、中间和最后一帧上运行它(在 bridge-stills 中),并在渲染前修复失败的镜头。自测试:npx tsx templates/scripts/framing_selftest.ts。

每个地点的光照(桥模板仅定义了白天和黄金时刻)

每个地点都需要在 lights.ts 中有自己的光照预设:清晰的关键光方向、双色调着色(暖色照明、冷色阴影)、接触和定向阴影,以及匹配的天空或天花板。绝不能有平淡无光的房间,也绝不能在房间内看到天空或云彩。

  • 室内(大厅、酒店、办公室): 天花板或深色墙顶,一束来自窗户或灯的关键光,温暖的实际光源(蜡烛、灯)带绽放,冷色阴影侧,柔和的暗角,每个道具的地板和墙壁阴影,来自窗户的光柱或灰尘。
  • 夜晚: 月光蓝色关键光(约 #5b7fd6),深蓝紫色阴影,温暖的亮窗和灯作为对比,月盘或星星。
  • 日出/日落: 带神光的低太阳,桃色至粉色天空,紫色阴影,长阴影。
  • 这些是起始值:根据 references/frames/ 使用并排对比图(sbs_sheet.py)进行调整。
  • 每个角色和道具下的接触阴影,加上来自关键光的方向性阴影尾巴;家具和道具在室内向地板和墙壁投射阴影(卡片阴影是真实的,不是模糊块)。
  • 景深(见下表)一致应用:特写和中景从不完全清晰,远景保持清晰。

摄像机多样性(始终移动,连续两次动作从不相同)

  • 在流程或镜头中,使用命名移动:慢推入、拉远揭示、围绕主体轨道、带视差的横向跟踪、起重机升降、倾斜、从前景道具到主体的变焦切换、小荷兰角度滚动(4-5°)。
  • 连续两次移动不得相同。
  • 在约三分之一的镜头中,在镜头和主体之间放置前景道具(柱子、栏杆、家具),以便摄像机运动呈现深度感。
  • 每个故事至少两个插入镜头:节拍 4-6 中机制的特写或剖面镜头,加上一个戏剧性角度(低角度英雄或鸟瞰)。
  • 保持现有的平滑步进滑行(18-40 f)、缓慢静止和冲击踢。

连续流程:在主体之间移动,不要剪辑(参考……)

(由于原始内容被截断,此处翻译基于已有文本。完整版应包含连续流程、反应和对话节拍、质量门、深度参考表、模板结构等剩余部分。请根据完整 SKILL.md 继续补充。)

相关技能