电影级3D视频
Claude 无法直接生成视频像素,但它可以编写3D场景代码、逐帧渲染并编码这些帧。本技能就是这条流水线。
场景 (HTML + Three.js) -- window.seek(t) --> scripts/render.mjs --> 无头 Chrome 截图 --> ffmpeg --> MP4
render.mjs 步进虚拟时钟,而不是实时录制。每台机器上的结果都相同,繁重的场景不会卡顿;它只会渲染得更慢。这就是为什么场景必须是时间的纯函数(参见“场景规则”)。
1. 首先检查工具
node -v # 22 或更新版本 (render.mjs 使用内置的 WebSocket)
ffmpeg -version
必须安装 Chrome、Edge 或 Chromium(会自动查找;设置 CHROME_PATH 可覆盖)。场景从 CDN 加载 Three.js,因此渲染机器需要互联网访问,除非 Three.js 已本地化(参见 references/troubleshooting.md)。如果缺少某个工具,请准确告知用户需要安装什么,并停止猜测变通方法。仅照片级真实路径才需要 Blender。
首次使用新机器时,运行一次无依赖的冒烟测试。它证明 Chrome、WebGL 和 ffmpeg 都正常工作,因此后续的任何问题都出在场景而非设置上:
node <skill-dir>/scripts/render.mjs <skill-dir>/templates/smoke-test.html --out smoke.mp4 --duration 2 --width 640 --height 360
2. 工作流程
- 确定需求:用一两句话概括:主题、氛围、时长、宽高比、任何文本、音频。当用户留空时,请选择默认值并说明你的选择:1920x1080、30 fps、8-12 秒、深色背景、一个主角物体、一个摄像机运动、一个标题。竖屏(TikTok/Reels/Shorts)为 1080x1920。在开始之前问一个以上的简短问题通常不值得;首次渲染就是最好的问题。
- 从模板开始。 将
templates/starter/复制到工作目录 (cp -r) 并编辑index.html。它已经包含了渲染器、色调映射、工作室反射、辉光、阴影、种子随机粒子、摄像机路径、HTML 标题覆盖层和时间线钩子。替换主角物体、调色板、摄像机路径和文本;保留管道代码。 - 在渲染视频之前先看静态帧。 在忙碌的时刻以全尺寸渲染一小组帧,并打开它们(读取 PNG):
在此处修复构图、曝光、颜色和文本可读性。一张静态帧只需一两秒;完整渲染需要几分钟。node <skill-dir>/scripts/render.mjs my-video/index.html --stills 0,2,4,6,7.5 --out my-video/stills - 渲染一次。 选择设置,然后渲染整个视频:
node <skill-dir>/scripts/render.mjs my-video/index.html --out my-video/video.mp4 --width 1920 --height 1080 --fps 30 --scale 2--scale 2以 2 倍分辨率渲染然后下采样,这消除了锯齿边缘(仅对最终渲染值得)。长时间渲染应在后台进行并轮询进度,这样用户就不会对着静默的终端发愣。 - 验证文件,而非日志。 使用
ffprobe检查时长、大小和帧率;从 MP4 中提取两到三帧(ffmpeg -ss 3 -i video.mp4 -frames:v 1 check.png)并查看。然后将 MP4 和场景文件夹交给用户,以便他们进行调整。 - 修改 即更改场景并重新渲染。使用
--start/--end仅重新渲染某一范围,以迭代特定时刻。
3. 场景规则(以及原因)
- 所有动画都是
t秒的纯函数,在update(t)中设置。不能使用Math.random()(使用种子rng()),不能使用Date.now(),不能使用clock.getDelta(),不能在不同帧之间累积状态。渲染器可能以任意顺序、任意时间点调用seek,浏览器中的预览必须与视频完全一致。 - 页面约定 包括
window.seek(t)(同步绘制)、window.__duration(秒数)和window.__ready = true(资产加载完成后)。lib/stage.js中的installTimeline()实现了全部三个。详情见references/contract.md。 - 高于 1.0 的 HDR 颜色会使物体发光。 辉光仅拾取高于其阈值的像素,因此发光部分使用
new THREE.Color(hex).multiplyScalar(3..6);普通表面保持在阈值以下。 - 文本是覆盖在画布上的 HTML/CSS(截图包含整个页面)。它在任何分辨率下都清晰锐利,无需字体文件,并且可以通过
update(t)内部的普通样式变化进行动画。 - 在设置
__ready之前使用await加载资产(GLTF 模型、纹理、字体)。在资产到达之前渲染的帧将是视频中永久性的瑕疵。 - 保持一个简单的灯光故事:一个主光、一到两个彩色边缘光,以及基于图像的反射。在深色、略带反射的地板上使用反射材质(金属、玻璃、清漆)正是让画面看起来像“3D 动画”而非“网页演示”的关键。
references/cinematography.md提供了摄像机运动、节奏、缓动、灯光和颜色的配方。
4. 多场景、音频、其他格式
- 多场景视频: 将每个场景渲染为独立的 MP4,使用相同的尺寸、帧率和编码器设置,然后无需重新编码即可拼接:编写一个
list.txt,包含file 'a.mp4'行,并运行ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4。将交叉淡入淡出放在场景自身的时间线内(一个场景的最后几秒和下一场景的最初几秒都通过黑色/颜色淡出/淡入),而不是混合已完成文件,后者会导致所有内容重新编码两次。 - 音频:
--audio track.mp3将其混入并剪辑到视频长度。之后仅更改声音:ffmpeg -i video.mp4 -i new.mp3 -map 0:v -map 1:a -c:v copy -shortest out.mp4。 - GIF / WebM / 小尺寸副本: 用 ffmpeg 重新编码完成的 MP4;切勿仅为更改格式而重新渲染。
- 更改一个场景 意味着重新渲染该场景的文件(仅当交叉淡入淡出位于该场景中时,才需要渲染下一个场景)。
5. 何时改用 Blender
仅当需求需要实时引擎难以伪造的效果时,才使用 Blender(references/blender.md、templates/blender/render_blender.py):路径追踪的玻璃和焦散、体积光、次表面散射、流体/布料/烟雾模拟,或完全照片级真实的产品展示。它每帧渲染要慢得多,并且需要安装 Blender 4+;对于其他所有情况,Three.js 在极短的时间内就能获得良好的结果,并且迭代速度更快。
参考文件
| 文件 | 阅读时机 |
|---|---|
references/contract.md | 从头编写场景、加载模型/纹理,或调试“从未设置 __ready” |
references/cinematography.md | 让结果看起来更棒:摄像机、灯光、材质、缓动、节奏、颜色、文本、粒子 |
references/troubleshooting.md | 黑帧、渲染慢、CDN/离线设置、Windows/macOS/Linux 怪癖、非标准尺寸 |
references/blender.md | 照片级真实或模拟工作 |
scripts/render.mjs | 所有选项:node scripts/render.mjs --help |