真实感3D短片(Blender + Python)
每一帧都是对Claude使用Python构建的场景进行的真实Blender渲染。不使用任何AI图像或视频模型。
最终输出:1080x1920,30 fps,H.264编码,限制最高30 Mbps。路径:<skill> = 此文件夹。剧集位于
<project>/blender-shorts/<slug>/,下载的资源位于<project>/blender-shorts/assets/,频道选择存储在
<project>/blender-shorts/brand.json。使用 python <skill>/scripts/<name>.py 运行脚本。
首先阅读:references/style.md(规则),references/traps.md(在发明任何修复方法之前)。
设置(每台PC只需一次)
- Blender 5.x(在Program Files下自动查找;否则设置
BLENDER=<path to blender.exe>)。 python -m pip install numpy opencv-python-headless pillow;确保ffmpeg在PATH中。- 验证流程可用:将
examples/test-cell/复制到blender-shorts/test-cell/,然后依次执行build、still、frames、 finish。在RTX 3080笔记本电脑上,EEVEE快速渲染其90帧1080x1920图像大约需要2分钟。
步骤0:启动提问(始终执行,在所有工作之前)
使用AskUserQuestion工具分两轮提问,每轮最多四个问题,然后第三轮取决于语音答案。如果 blender-shorts/brand.json 已存在,先问一个问题:“是否使用与上次相同的设置?”(在一行中显示它们)并提供“是”/“更改一些”。如果回答“是”,则跳转到第三轮中与主题相关的部分。 推荐选项放在首位。将每个答案保存到 brand.json(频道级别)和剧集的 episode.json 中。
第一轮:内容及说话方式
- 主题:“为我建议3个”/“我有一个”(他们在“其他”中输入)。建议:关于身体或事物工作原理的问题,一定要有画面,并在YouTube上检查其角度是否原创。
- 语音:
- ElevenLabs语音(推荐):一个预设语音,根据脚本生成,带有精确的字词时间戳。
- 克隆我的声音(ElevenLabs):他们上传1-3分钟的清晰语音一次;之后每集都用他们的声音说话。仅限他们自己的声音,或已获得书面同意使用的声音。
- 我自己录制:他们录制脚本;Claude进行清理、找到字词时间戳,并据此构建画面。
- 无语音,仅字幕:脚本以稳定的2.8词/秒进行计时,字幕嵌入在视频中,并提供一个
captions.srt文件,让他们可以在后期编辑软件中按照精确的时间录制或添加语音。
- 时长:30秒(第一次推荐)/ 45秒 / 60秒。以2.8词/秒计算,大约80 / 120 / 165个词。
- 参考视频:“不,使用内置风格规则”(推荐)/ “是,我会提供文件或链接”(使用
measure.py进行测量,仅供私人研究)。
第二轮:外观
- 外观:工作室背景(推荐:在所有物体后面使用一种标志性颜色,这是该类型的标准外观)/ 真实世界照片背景板(3D物体后的体育场、街道、天空)/ 混合(背景板,在需要显示地点的节拍中使用真实场景)。
- 背景颜色(如果不使用背景板则跳过):桃色
#F2D7C9(我们目前使用的)/ 薄荷绿#CFE8DF/ 深海军蓝#1F2A44/ 自定义(十六进制)。绝对不要使用参考频道的颜色。 - 主要角色:“是否有主要角色?”(
references/characters.md)- 我将提供一个已绑定的角色:他们的.blend / .fbx / .glb文件(来自Mixamo、Character Creator或商店)。
- 为我制作一个(如果他们还没有,推荐使用):在Blender中使用MPFB构建,无需账户,衬衫上有我们的Logo。
- 下载一个免费绑定的角色:Claude提出2-3个候选(来源、许可证、外观);在需要账户的网站(Mixamo、Renderpeople、Sketchfab)上,用户下载并提供路径。
- 没有角色:仅使用物体、身体部位和场所。
一旦主要角色存在(
assets/host/host.blend),这个问题变为“再次使用<名字>?”。
- 渲染引擎:
- 自动(推荐):大部分场景使用EEVEE快速渲染,仅在皮肤特写、云、玻璃或头发等方面失败的镜头快速使用Cycles。
- 仅EEVEE快速:最快的选项,每帧约1秒。
- 仅Cycles快速:速度大约慢2倍,光线更柔和、更自然。
- 高质量:使用
high预设,速度比快速慢约2-3倍。
第三轮:取决于语音答案
- ElevenLabs或克隆:关键步骤。 检查项目或上级目录中是否有
.env文件包含ELEVENLABS_API_KEY=(绝不要打印出来)。如果存在,提示“找到你的ElevenLabs密钥”,不再询问。如果不存在,则询问: “请添加你的密钥:粘贴到此,我会保存到.env,或者自行在.env文件中添加一行ELEVENLABS_API_KEY=...(这样密钥就不会出现在聊天记录中)”。将粘贴的密钥仅保存到<project>/.env,绝不要输出它,绝不要将其放入任何其他文件、提交或日志中。 - ElevenLabs:语音:冷静叙述者(默认ID在
sound.py中)/ “从我的ElevenLabs库中选择”(使用GET /v1/voices列出,仅显示名称)/ 语音ID(他们输入)。语音模型:eleven_multilingual_v2(推荐:稳定,字词时间戳最佳)/ eleven_v3(更具表现力,但预测性稍差)。 - 克隆:要求提供样本文件(路径),然后执行
sound.py <ep> clone <files> --name "<他们的名字> voice";语音ID会被保存并被后续每集重用。 - 自己的录音:告知他们等待脚本获得批准,然后一次性录制,手机距离一臂远,在安静的房间内,并提供文件路径。(对着批准的脚本录音才能确保画面和语音同步。)
- 主要角色,根据第二轮的答案:
- 提供:要求提供文件路径(如果纹理文件夹单独存放,也一并提供)。
- 制作一个:询问年龄段、体型、发型和服装风格(用简单语言描述);然后要求安装MPFB。
- 下载:展示2-3个候选作为选项(名称、外观、许可证、是否需要账户),让用户选择。
- 每种语音选项:是否嵌入字幕? 是 / 否(无语音选项始终包含字幕)。
- 每个选项:音乐:无,仅音效和环境音(首次推荐)/ 我自己的曲目(文件路径,用户确认拥有版权)/ YouTube音频库曲目(用户下载并提供路径)。
不要询问其他任何事情;以下是所有默认设置。“特定模型”问题:此流程中没有AI图像或视频模型。与其功能类似的选择是渲染引擎(第二轮)、ElevenLabs语音模型(第三轮)以及运行该技能的Claude模型:在高度努力设置下使用Opus效果最佳。
引擎预设(用户选择的设置,保持不变)
- EEVEE快速(默认,
b3d.EEVEE_PRESETS['fast']):16个样本,半分辨率光线追踪和全局光照,1条阴影光线。 在3080上1080p下每帧约0.9-1.2秒,与high相似度达99-99.9%。 - Cycles快速(
b3d.CYCLES_PRESETS['fast']):32个样本,1秒时间限制,OptiX降噪器,2-3次反弹,快速GI近似值,持久数据。每帧约1.7秒。如果降噪器模糊出现在特写镜头上,则将该镜头的时间限制设为2秒。 - 渲染时使用
--quality draft | fast | high,无需重建。每个场景的渲染引擎通过setup_render(engine=...)设置,或通过B3D_ENGINE=CYCLES python render.py <ep> build进行A/B测试而无需编辑。如果背景和调色匹配,一个短片中混合使用引擎是可以的(每个镜头从各自的.blend文件中渲染其帧范围)。
流程(每一步后保存;向用户展示图像,避免大段文字)
- 主题和事实。 计算出每个数字并将其来源写入
episode.json的science字段。不可靠的著名数字使用“科学家估计”。与大频道主题相同是可以的,但不使用他们的措辞。 - 测量参考(仅第一轮回答“是”时):
measure.py <folder> --out <ep>/reference.json。否则使用style.md中的默认值。 - 脚本 在
episode.json中(examples/episode.template.json):第二人称,约2.8词/秒,选定的时长,style.md中的节拍形状。显示脚本并等待确认。确认后,继续执行直到生成图像。 - 语音和时间戳,根据第一轮答案:
- ElevenLabs / 克隆:
sound.py <ep> voice->audio/voice.wav,words.json,captions.srt。 - 自己的录音:等待其文件,然后执行
sound.py <ep> own <file>(字词时间戳:如果安装了faster-whisper则使用它,否则如果有密钥则使用ElevenLabs语音转文本,否则根据静音估计;如果估计不准,提供pip install faster-whisper)。 - 无语音:
sound.py <ep> captions->words.json+captions.srt,速度为"wps"(2.8)。 然后编写shots.md:每个节拍包含帧范围(来自字词时间戳)、摄像机运动(推入/保持+微移/拉出/飞越)以及每个保持期间哪些物体持续运动。每约7个转场最多允许1个硬切。
- ElevenLabs / 克隆:
- 首先进行9秒测试。 在制作整个短片之前,先对一个节拍运行完整流程:使用
b3d辅助工具运行scene.py。渲染、完成、measure.py,如果有参考则执行compare.py reference.json ours.json。差异列表就是待办事项列表。 修正摄像机,直到抖动和横向漂移匹配(一个轴,缓动关键帧)。 - 世界和角色。 角色优先,根据其在
references/characters.md中的路径,始终通过b3d.import_character(path, height=1.75)导入:它会将角色缩放到真实高度,脚着地面,移除多余的摄像机和灯光,将有重量的部件绑定到骨骼上,并打印一份报告(骨骼类型、未跟随骨骼的部件、面形 x/52、缺失的纹理)。修复报告中的每个问题,然后制作一张旋转展示静帧,保存为assets/host/host.blend。世界来自references/assets.md(列出下载,包括来源、许可证和大小,询问一次)。规则:如果存在真实的资源,则下载它,绝不自己建模。 - 静帧和评判。 针对每个节拍,执行
render.py <ep> still <frames...> --pct 50。然后生成一个单独的 Agent(Agent工具),向其提供静帧和references/realism.md,它给出10分制的评分并指出三个最明显的破绽。修复、重新渲染、重新评判。只有在得分8.5以上时才进行渲染。 向用户展示静帧和评分。如果使用“自动”引擎,某个在EEVEE快捷方式上失败的镜头将在此处切换到Cycles快速渲染。 - 渲染。 在用户的终端面板中运行
render.py <ep> frames(使用run_in_terminal),以便他们实时查看进度条(已完成的帧数、每帧秒数、预计完成时间);通过读取<ep>/progress.json来回答“渲染到什么程度了?”。可断点续传。之后运行render.py <ep> times;如果太慢,针对最慢的帧按照references/render-speed.md中的步骤进行优化。 - 声音。 在
episode.json中设置beds(每个世界一个环境音)和sfx(每个对应其字词:例如在“bones”上播放“bone knock”),然后运行sound.py <ep> sfx(需要密钥;如果没有密钥,则跳过音效或使用用户在audio/sfx/<name>.mp3中提供的文件)和sound.py <ep> mix。混音规则:音乐 +3 dB,音效减半,人声不变。 - 完成。 执行
finish.py <ep> --audio <ep>/audio/mix.wav [--captions]->out/<slug>-final.mp4。以手机尺寸观看。无语音剧集:同时移交captions.srt,并说明语音会按照这些时间点加入。 - 报告:最终文件路径、评判的最后评分、渲染分钟数、ElevenLabs信用点(
costs.json)、以及用于描述的版权信息文本(assets.md中的许可证)。绝不要声称参考频道使用了任何工具。
脚本
| 脚本 | 运行环境 | 功能 |
|---|---|---|
b3d.py | Blender | 渲染设置 + 预设(EEVEE/Cycles, GPU,外观),背景板 + HDRI,阴影捕捉器(Cycles下真实,EEVEE下模拟),灯光,单轴缓动推拉摄像机,材质,import_character(任何绑定的.blend/.fbx/.glb,缩放,绑定,报告),parent_to_bone,形态键,合成器,计时器 |
render.py | shell | build,still,frames(实时进度条,progress.json,可断点续传),times;--quality |
sound.py | shell | voice(ElevenLabs),clone,own(用户录音),captions(无语音),sfx,mix;每种语音模式都会写入 captions.srt |
finish.py | shell | 帧 + 混合音频 -> 1080x1920 MP4,真实摄像机图层,--captions 嵌入字幕 |
measure.py / compare.py | shell | 任何视频的逐帧指标;参考与我们的视频对比,生成待办事项列表 |
scene.py 通过 blender -b --factory-startup --python scene.py -- <skill>/scripts <ep>/scene.blend 调用;
从 examples/test-cell/scene.py 开始(在灯光之后调用 shadow_catcher)。