AI 做视频 · Three.js 3D
不用摄影机也能拍一镜到底
从城市上空落进一扇窗,跟着一句话穿过机房、钻进芯片——这段一镜到底没有摄影机,也没有一张图片、一个模型文件,全是一个网页里的 Three.js 代码算出来的。下面就是那个网页,现在正在你的浏览器里实时跑。
一句话的旅程:30 秒一镜到底
镜头一共 8 小段:绕着城市落下来(交代地点)、推进窗户(交代主角)、贴地追光点(速度感)、沿机房过道往里推(纵深)、冲进芯片(从大世界掉进小世界)、在网络里先冲再侧着拉开(看清一层层)、最后拉出窗外回到开头。每一段都是一个「给我时间,我给你机位」的小函数,段和段之间用一秒左右混合过去。
示意:真实的网络不会发光,也不走马路。比较吃显卡,手机上可能会卡。下载、拿提示词 →全屏打开 ↗
3D 就是搭一个片场
平面的做法像在纸上画画;Three.js 更像搭片场:搭景(方块、球、圆柱)、打光(太阳从哪照过来)、摆机位(摄影机站在哪、看哪里)、按快门(算出摄影机看到的画面)。想让镜头推近、绕一圈,不用重画任何东西,景不动,只是把摄影机挪一下。
搭景 → 打光 → 摆机位 → 按快门全屏打开 ↗
镜头怎么动才好看
做之前先看了这阵子做得最好的两条。Prasenjit 让 Claude 做的两分钟电子游戏史[1]:讲到 1993 年,镜头在走廊里一路往前推;1996 年一座线框城堡变成实体,镜头往后退、往上升,才发现它浮在天上——往前推是时间在走,往后拉是看到更大的世界。他的提示词只有三段:
make a cinematic 2-minute video on the history of video games. make it epic and emotional, like a documentary trailer. go all out. compose the soundtrack yourself, fully synthesized in code. no samples, no audio files, no VST instruments. cut the visuals to the music. 1920x1080, 60fps. no downloaded images or footage, every frame generated in code. render the final video with the music mixed in as an MP4 and save it [here] (your preferred file location)
宝玉用 Three.js 重做的《桃花源记》[2],提示词里有一段专讲镜头:远望要看得见层次,前进要有遮挡和引导,靠近要看得见细节,转折处要把空间揭开;不要全程高空俯瞰、匀速绕圈、突然转向、大幅摇晃。说白了:镜头每动一下,都得有个理由。
提示词:拿去就能用
示范片是一边写代码、一边出静帧看、一边改出来的,下面是把实际做法整理成的提示词,丢给 Claude(或者任何会写代码的 AI)就能做出差不多的片子。想换题目,改「direction」和「structure」两段。
<role>
你是 3D 动画导演,也是创意程序员。用一个独立的 HTML 文件 + Three.js(ES 模块,importmap 引本地的 three)做一段 30 秒、1920×1080 的一镜到底,最后拍成 MP4。不用任何外部图片、3D 模型文件或网络请求,所有东西用代码搭。
</role>
<direction>
题目:你发给 AI 的一句话,跑到哪儿去了(示意,不追求真实)。风格:低多边形积木风的小城,黄昏,暖色窗光 + 冷色机房 + 一个荧光黄绿的光点贯穿全片。
镜头每动一下都要有理由;禁止:全程高空俯瞰、匀速绕圈、突然转向、大幅摇晃、满屏金色粒子、只有环境光的平光(塑料感)、用浓雾盖住空场景。
</direction>
<structure>
0–5 秒 绕:从城市上空侧着绕下来,夕阳在楼后(逆光),交代地点。
4.5–8 秒 推:推进主角楼的一扇窗,屋里台灯、书架、一台笔记本,屏幕上一句话打出来、发送。
8–10.5 秒 光点从笔记本出发,沿一根线缆爬过窗台、顺着外墙往下,镜头跟着往下摇。
10.5–13.5 秒 跟:镜头贴地追着光点沿马路飞,路灯一盏盏掠过,远处是一座亮着蓝色灯带的数据中心。
13.5–17.5 秒 推:进门,机房过道左右对称,两排机柜的指示灯在闪,沿过道往里推。
17–19 秒 冲:光点钻进一台机柜,镜头转过去冲进显卡上的芯片,金线越来越亮,闪白。
19–25.4 秒 芯片里面:14 层点阵(每层 40×24 个点),信号一层层往里传、亮起一部分点和连线;镜头先贴着信号往前冲,再侧着拉出来看清一整摞;最后一层冒出一个亮点冲向镜头,闪白。
25.4–30 秒 拉:回到笔记本屏幕前,回答一行行出来,镜头一路拉出窗外、升到高处,回到开场那座城。
</structure>
<build>
1. 页面暴露 window.render(t):画面只由 t 决定(光点位置、车、指示灯闪烁、屏幕上的字、镜头全部是 t 的函数),不用 requestAnimationFrame、不用 Clock;随机数带固定种子。
2. 镜头:每一段是一个小函数 rig(t) → { pos, look, fov };相邻两段在约 1 秒的交界里把位置、朝向、视角线性混合;每段内部用慢起慢停的缓动。
3. 线缆是一条 CatmullRomCurve3(centripetal),光点按「时间 → 第几个控制点」的关键帧(单调三次插值)在曲线上走,后面拖一串越来越淡的发光精灵当拖尾。
4. 光:一盏低角度的夕阳 DirectionalLight 投影子 + 半球光 + 一点正面冷色补光;天空是一个大球的着色器渐变(地平线橘粉 → 头顶深蓝)+ 星星;FogExp2 做空气透视;UnrealBloomPass 泛光 + ACES 色调映射。
5. 省性能:楼的窗户是随机亮格子的 CanvasTexture 当 emissiveMap(只亮约两成多),路灯的地面光圈是叠加混合的径向渐变贴图,不点真的灯;机柜和指示灯用 InstancedMesh。
6. 拍摄:起一个本地静态服务器(ES 模块不能从 file:// 加载),Playwright 打开页面,逐帧调用 render(i / 30) 并截图(900 张),喂给 ffmpeg 压成 MP4。没有显卡的机器上 Chromium 会自动用 SwiftShader 软件渲染,能跑,约 1 秒一帧。
7. 配乐用 Python numpy 合成:和弦铺底随场景换和声,光点出发后加拨弦琶音,机房加底鼓,进芯片和回屏幕各有一次呼啸 + 低音,穿过每层网络有一声小铃。
8. 留开关 setup({ lights:'flat', fog, bloom, god, cam }):关灯光/雾/泛光做对比;god 是上帝视角(画出镜头走过的路和它的视锥);cam 是单独的练习镜头(绕圈、推、变焦、晕眩镜头)。
</build>
<gotchas>
- 每做完一段就渲 3 张静帧自己看:镜头有没有卡进楼里、主体够不够大、亮的东西有没有糊成一片。
- 光点贴着墙走时,光晕精灵会被墙切掉一半(变成吃豆人):线缆离墙远一点。
- 窗户亮灯太多会像一块 LED 屏,夜景要少。
</gotchas>
用 Three.js 做一段 25 秒、1920×1080 的教学动画,window.render(t) 驱动,奶白色地面 + 细网格,道具带黑色描边: 0.3 秒 搭景:方块、球、圆柱、圆锥依次从空中掉下来弹一下(只有均匀的环境光,看起来很平); 5 秒 打光:一个卡通小太阳出现,虚线连到场景中心,换成一盏斜上方的平行光,出现柔和的影子; 9.6 秒 摆机位:一台黑色小摄影机模型飞进来停在斜前方,用 CameraHelper 画出它的四棱锥; 13.7 秒 按快门:闪白,切到这台摄影机看到的画面,四角加取景框和「● CAM 1」; 18 秒 这台摄影机一边推近一边绕着道具转大半圈; 22.6 秒 切回旁观视角,用一根红色的管子画出它刚才走过的路。
没有显卡也能拍:Chromium 会自动用 CPU 软件渲染(SwiftShader),阴影、泛光都正常,就是慢——1080p 大约一秒一帧,30 秒的片子要算十几分钟。
引用
- 电子游戏史短片:Prasenjit(@prasenx),x.com/prasenx/status/2103851939457093635;提示词:x.com/prasenx/status/2103868196172480793
- 《桃花源记》:宝玉(@dotey),x.com/dotey/status/2102940980379017293
- xilo(@xilo2991)的《零基础入门 Opus 5.5 做视频》,x.com/xilo2991/status/2104912748794589515
用 AI 做出来的好玩东西,我都会拆给你看
每天的 AI 新闻,加上几分钟讲透一个概念。

