我想做一期关于自家宽带被限速的视频,事情本身不复杂——怎么发现、怎么排除、最后怎么解决,一条线讲清楚就行——难点全在画面上:这类内容需要的是准确的链路图、真实的测速曲线,而不是一段看起来很漂亮的影像。而我手上只有文字模型。这在一两年前基本等于"做不了"。
最近折腾下来发现路子是有的,只是跟大多数人想的不一样——不是让模型去"画"画面,而是让它去"写"代码,写完交给本地的渲染器执行。这篇把我踩过的坑、算过的账,以及两套可以立刻上手的安装方式都记下来,省得后面再有人从头摸一遍。
先说结论
- 文字模型做视频,靠的不是生成像素,是生成代码。 模型输出 SVG、React 组件或者 Python 绘图脚本,本地渲染器把代码变成帧,ffmpeg 把帧变成视频,全程没有第二个 AI 参与。
- 这条路能做到的事比想象中多,架构图、数据动画、界面演示、几何动效、三维场景都能覆盖;做不到的也很明确,照片级人像和真实风景需要一个"见过世界"的模型,写代码的模型给不了。
- 成本结构和生成式视频完全不同。 生成式按次或按秒计费,改一版重来一次;这条路只在写代码和提需求时消耗 token,渲染吃的是本机算力,改一百遍也不额外花钱。
- 幻觉的表现形式变了,但没有消失。 生成式视频是画面里多出一根手指,这条路是代码里多算了一个坐标,好在后者能跑测试、能看报错、能被程序验出来。
- 装起来不算麻烦,但有几个坑必须绕。 素材包 145MB、渲染运行时 230MB、再加一个 ffmpeg,国内网络下这三样各有各的脾气,我会把实测的绕法写清楚。
- 60 秒 1080p 全片,这台机器渲染用了 181 秒。 后面有一项可能反直觉的结论:GPU 在这条路上基本帮不上忙,加钱换硬件不如改代码。
下面按四块讲:先看现在这条路卡在哪,再说语言模型凭什么能绕过去,然后是两套现成方案的安装步骤和踩坑记录,最后是我实测出来的数据。安装那节写得比较细,因为那里最容易劝退——不是难,是坑藏得深。
现在的 AI 视频工具,两个绕不过去的坎
成本不是线性增长,而是"改一次付一次"
生成式视频的计费逻辑是按产出算,一次生成几秒、什么分辨率,对应一个价格。这套逻辑对"一次性出片"很友好,对"反复调整"就很不友好,而做视频这件事本身恰好是反复调整的过程——第一版出来,字太大、节奏太拖、某个画面停太久,这些都得重来,每一次重来都是一次完整计费,而你要的可能只是把某个元素往左挪三十个像素。
按 token 计费的文字模型走的是另一套算法——具体的消耗怎么查,我做过一个用量看板(WorkBuddy 的 token 用量怎么看):需求描述、代码生成、报错修正消耗的是 token,渲染吃的是本机 CPU,中间没有按次收费的环节,这意味着改十遍和改一遍的边际成本几乎一样,除了你自己花掉的时间。顺便说一句,这不等于文字模型一定更便宜——如果要生成的量大,本地渲染的时间和电费也是成本,只是成本的形状不一样,一个跟着次数涨,一个跟着复杂度走。
真正麻烦的地方还在于,生成式工具很难让你"只改一处"。它输出的是一整段像素,你想动其中的一个角落,往往得重新生成整段,而重新生成意味着其他地方也可能跟着变——上一版满意的构图、配色、节奏,这一版未必还在。改到第三第四遍,经常会陷入一种状态:新版本修好了 A 却搞坏了 B,翻回去看第一版反而更顺眼。时间就在这种来回里耗掉。
话说回来,生成式视频有它无可替代的地方,我没打算否定它。真实的火焰、人群、雨滴、爆炸、皮肤质感,这些用代码画一万行也画不像,而生成模型几秒钟就能给你一段。所以这两条路不是替代关系,是分工关系:要"真实世界的质感"用生成式,要"准确的结构和可复现的细节"用代码。我这次的需求恰好落在后者——一张流程图的节点位置错一格,比画面不够漂亮严重得多。
幻觉换了张脸,识别难度却不一样
AI 生成视频的"幻觉"很好识别:手指数不对、文字变成鬼画符、物体穿过墙壁、人物走路像滑行。这类问题的成因我在这篇里写过(AI 幻觉是怎么产生的),说到底是模型在补全它并没有真正理解的东西,它知道"手大概长这样",但不知道"五根手指怎么连到掌骨"。
用代码做视频,幻觉不会消失,只是换了个样子。坐标算错,两个元素叠在一起;字号写大了,文字冲出画面;缓动曲线给错,动画看起来像卡带;时间轴对不上,画面和音效差半秒。这些东西在渲染之前看不出来,渲染之后一眼就看得见。
区别在于这些错误都能被程序抓出来——渲染出来的帧可以做像素统计,查非空区域占比、查元素边界有没有越界,ffmpeg 能验音轨是否存在、响度是否达标,代码本身还能跑一遍类型检查,三道关下来,大部分低级错误在你打开播放器之前就已经被拦住了。生成式的错误只能靠人眼一帧一帧看,而人工检查的覆盖率和重复性都靠不住,看第十遍的时候你已经开始走神了。这才是我愿意折腾这套东西的真正原因——不是它更强,是它错了之后我能查。
语言模型怎么把文字变成画面
核心:它不产生像素,产生指令
先把一个容易混淆的点说清楚。DeepSeek 这类模型的输出永远是 token,是一串文字,它没有能力直接输出一张图的像素矩阵。所以要让模型"做图",中间必须有一层翻译,而这层翻译不是另一个 AI,是一个确定性的执行器——同样的输入永远得到同样的输出,没有随机性,也不存在"这次生成得比上次好"。
具体分三条路线,区别只在于"图"用什么方式描述:
| 路线 | 图是什么 | 适合做什么 | 工具 |
|---|---|---|---|
| 矢量 | 一组几何指令 | 示意图、图标、版式、封面 | SVG、HTML/CSS、Canvas |
| 数值 | 一个数字矩阵 | 图表、纹理、程序化背景 | Pillow、numpy、matplotlib |
| 时序 | 一串带时间戳的帧 | 动画、视频、演示 | Remotion、manim、ffmpeg |
最直观的例子是让它画一个圆,这时你会发现它并没有在"想象"一个圆,而是写出一段代码:新建一张 1080×1080 的深色画布,在坐标 (440,440) 到 (640,640) 之间画一个椭圆,填充色是十六进制 #2dd4bf,最后存成 PNG。这段代码跑起来必定得到一个圆,位置、颜色、大小全是确定的,改颜色不过是改一个十六进制值、改大小不过是改两个数字,而且改完之后重新跑一遍,除了你动的那处,其他像素一个都不会变。矢量路线更进一步,连像素都不落盘,直接输出 <circle cx="540" cy="540" r="100" fill="#2dd4bf"/>,交给浏览器或者 rsvg 去栅格化——好处是无限缩放不糊,而且生成出来的文件本身还能再编辑。
视频只是在这上面叠一层时间。把画圆的代码包进循环,每帧改一个参数,导出 300 张 PNG,最后交给 ffmpeg 合成:
ffmpeg -framerate 30 -i frames/%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4
就这么两步。听起来简陋,但它能做出什么,完全取决于喂进去的代码有多复杂,而代码复杂到一定程度,就是 Remotion 那种"用 React 写视频"的框架了——每一帧是 React 组件渲染出来的结果,动画曲线、时间轴、音频轨道全部用代码描述,改一个变量,整条片子跟着变,不需要回到时间线上重新拖一遍。
为什么偏偏是文字模型能干这事
这里有个反直觉的地方:做视频需要的能力,恰好是语言模型最擅长的。React 组件、CSS 布局、SVG 路径、Python 绘图,这些东西的共同点是有语法、有文档、有海量公开代码,模型在训练时见过大量同类样本,写起来相当稳。
反过来,让模型直接预测像素,需要的是完全不同的能力:理解三维空间、理解光照、理解材质,还得知道一个杯子放在桌上时影子该往哪边倒。这是多模态生成模型的赛道,和语言模型不是一回事,也不是靠多写几行提示词能补上的。所以准确的说法不是"DeepSeek 会做视频",而是"DeepSeek 会写做视频的代码,而代码在本地跑起来就是视频"。这个区别看着像文字游戏,实际上它决定了能力边界在哪、你该在什么场合用它,以及出了问题该往哪个方向查。
顺带说一句,模型对 SVG 和 HTML 的掌握程度明显好于对三维引擎的掌握:让它画一个二维流程图,一次就对的概率很高,而让它写 three.js 的场景,往往要来回改上几轮才能把相机位置和光照调对。这不是模型笨,是训练数据里三维代码本来就比二维代码少一个数量级。
需要补的那一环:它看不见自己的成果
纯 API 调用有个死结,模型写完代码,不知道跑出来长什么样。我一开始以为这是小事,实际上它是这条路上最大的效率损失点。
代码里的错误分两类。一类会崩,好办,报错贴回去它就改了。另一类不会崩但难看:元素重叠、字号失衡、动画卡顿、留白比例不对。后者没有任何报错,模型只能靠想象,而它对"这段代码渲染出来大概什么样"的想象经常是错的。
具体到实际写场景,模型最容易栽在三个地方。坐标系上,它习惯按"居中""靠右"这类相对描述写,但代码里必须给绝对像素,1920 宽的画布上写 400 还是写 800,它得自己算,算偏了元素就挤在一起。字号上,中文和英文的字宽不同,同样写 fontSize: 48,一句十个汉字和一句十个字母占的宽度差了将近一倍,模型经常按英文的直觉给尺寸,结果中文一长就出界。时间轴上,缓动函数给 0.3 秒还是 3 秒,看起来只是数字,实际决定了动画是"利落"还是"卡带"。
这三处都不是逻辑错误,跑测试也测不出来,只能靠看。所以第一条建议是把画布尺寸、安全边距、正文字号写进场景文件顶部的常量里,让模型每次改都引用同一个值,而不是重新拍一个数。第二条是渲染关键帧拼图,一次看六帧比逐帧看省事得多。
解决办法有两个方向。一条是给模型加上"看"的能力,让它能直接读渲染出来的帧,看完自己判断哪里不对;另一条是把视觉判断翻译成程序判断,比如算出非空像素比例、检测元素边界框是否越界、比对相邻帧的差异度、检查文字区域有没有和图形重叠,用数值代替眼睛。第二种在模型完全没有视觉能力时也能挡住大部分问题,这也是为什么需要一个完整的宿主环境——随便找个聊天框贴代码,是没法形成闭环的。
怎么装:两套现成的方案
前面说的原理,真要落地得有封装好的工具链。目前有两个可以直接用的东西,底层是同一套引擎(Remotion 加 React 加 three.js),区别在于跑在哪个宿主里。
| WorkBuddy 技能包 | DeepSeek Harness 插件 | |
|---|---|---|
| 形态 | 命令行工具 wb | 图形界面插件 |
| 要不要画布 | 不要 | 要,右侧栏有可编辑画布 |
| 适合 | 纯做视频,写代码出片 | 先画结构图或分镜,再转视频 |
| 安装难度 | 解压即可 | 需要宿主加插件市场 |
两者共享素材和运行时目录,装了一套另一套不用重下那三百多兆。这件事一开始我没太在意,后来发现它省的不只是流量——两套东西用的是同一份字体、同一份采样、同一份渲染依赖,你在插件里调好的字体和音效,切到命令行出片时完全一致,不会因为环境不同产生色差或者字形差异。对于需要反复迭代的片子,这种一致性比省流量重要得多。
方案一:WorkBuddy 技能包
这个叫 drawai-video-studio,是把引擎 vendor 成独立 CLI 的技能包,来自开源项目 dsh-drawai,MIT 许可,GitHub 上五百多个 star,npm 上个月下载一万二千多次。项目是单人维护,但从提交记录看工程化程度不低——有 CI、有回归测试、有发版闸门,两个月推了二十多个版本。
装法是把 skills/workbuddy 整个目录拷进 WorkBuddy 的技能目录,然后在里面跑自检:
node scripts/wb.mjs doctor
它会检查四件事,缺什么会直接告诉你补什么。四项全绿就能建工程:
node scripts/wb.mjs create --dir ./my-film --spec 1920x1080@30 --duration 5
这一步会生成工程骨架:时间轴 timeline.json、每段一个 scene-N.tsx、分镜表、素材目录。剩下的工作就是改那些 scene-N.tsx 里的 React 组件,说白了就是写网页,只不过每一帧都会被截图存成视频。
方案二:DeepSeek Harness 插件
先在 deepseek.com/harness 装桌面版,可以装到用户目录,不需要管理员权限。启动之后在插件市场搜 dsh-drawai,装完完全退出再重开,右侧栏会出现「DrawAI 画布」。第一次用要先走 文件 → 新建画布…,空面板不会自动建文件,这点容易误解成装坏了。
装完第一件事是确认版本。0.4.5 有个明确的 bug:中文路径的画布会打开成空白,或者按编码串误建一个空文件。如果你的工程目录带中文,必须升到 0.4.6。另一个 0.4.6 修的坑跟 ffmpeg 版本有关,motion_audio_verify 里用的 -vsync 0 参数在 FFmpeg 7 就弃用、9 已经删掉,装的是新版 ffmpeg 就会报 Unrecognized option 'vsync'。
两个版本我都实测过,这两个 bug 在 0.4.6 里确实没了,所以别图省事停在旧版。
装完之后怎么判断"能跑了"?插件版看右侧栏有没有画布,技能版看自检输出。自检那四项的含义值得解释一下,不然看到红色会不知道从哪下手:babel 是场景代码的语法校验器,缺了它连改错都发现不了;素材 是字体和纹理,缺了画面能出但字会变成默认黑体;运行时 是 Remotion 那套渲染依赖,缺了根本渲不出来;ffmpeg 负责拼帧、抽帧、混音和响度归一,缺了能出静帧但出不了成片。四项全绿之后建一个工程,目录大概长这样:
my-film/
timeline.json 时间轴:规格、每段起止帧、音轨
scene-0.tsx 第一段的组件,后面依次排
storyboard.md 分镜表,六列,给人看的
assets/ 素材、字体、内置音效
.out/ 渲染产物、任务记录、质检报告
改画面只动 scene-N.tsx,改节奏只动 timeline.json,两者不互相干扰。这一点设计得挺舒服——你可以把一段挪前挪后,而不用回头改场景里的常数。
三样依赖,三个坑
不管走哪条路都要准备这些东西,我把踩过的都写出来。
素材包,约 145MB,解压后 200MB。 里面是字体、纹理和一百多个乐器采样,默认从 GitHub Release 下载,而国内网络的实际情况是:它会走 Node 内置的 fetch,偏偏 fetch 不认 HTTP_PROXY 环境变量,于是你以为自己在走代理,实际上一路直连。
这一条值得单独说,因为它的表现特别有迷惑性。Node 18 以后的全局 fetch 基于 undici,默认完全忽略 HTTP_PROXY 和 HTTPS_PROXY,所以我明明设了代理环境变量,下载速度还是卡在 3 到 21 KB/s——请求根本没进代理,一直在直连 GitHub。更麻烦的是这种直连不会"失败",只会一直慢,于是下载器里那条"失败就退回用 curl"的兜底逻辑永远等不到触发条件,你以为在等代理干活,其实是它在慢慢爬。
实测数据很说明问题,同一个文件:
| 方式 | 速度 |
|---|---|
| Node fetch 直连 | 3–21 KB/s |
| curl 显式走代理 | 87 KB/s |
| 国内镜像直连 | 478 KB/s |
解法不是修代理,是换源。引擎支持 DRAWAI_ASSETS_URL 环境变量,指到一个能直连的镜像就行,速度和稳定性都上一个台阶。
视频运行时,约 230MB。 Remotion、React、three.js 这些依赖,首次渲染自动装,也可以提前装。这部分走 npm registry,国内通常没问题,但要注意装完别急着渲染,先跑一次自检确认依赖数量对不对——我有一次卡在这,是因为依赖只装了一个包,剩下八个在排队等网络。
ffmpeg,这个最坑。 引擎只保证"找一个能用的 ffmpeg",不负责帮你装。我试了三种方式:
| 方式 | 结果 |
|---|---|
ffmpeg-static npm 包 | 下载到 62MB,有 PE 头但跑不了,正常应该在 78MB 以上 |
@ffmpeg-installer/ffmpeg | 同样截断,58MB |
pip install imageio-ffmpeg | 105MB,四秒下完,能用 |
前两个都是被截断的文件,MZ 文件头还在,可后面的节区不全,执行时报 Exec format error,清缓存重装也没用,换网络也一样。最后走 PyPI 是歪打正着:imageio-ffmpeg 把 ffmpeg 二进制直接打进 wheel,走清华源几秒就下来,还有完整性校验。装完把 exe 复制到一个固定目录,加进 PATH 就行。顺带说一句,ffprobe 我是从 @ffprobe-installer/ffprobe 拿的,那个包没坏。
还有个小坑,wb preview --at 的单位是秒不是帧号。我第一次传了 60,400,700 想取六个关键帧,它把数字乘了帧率,报"帧号要在 0–1799 之间:1800,12000,21000"。
实测账
装完跑了一条 60 秒的片子验证,六段结构:标题、速率曲线坠落、逐段排除、瓶颈定位、通道恢复、结论,1800 帧,1080p。之所以选这个题材,是因为它把三类难点都占全了——曲线要用矢量路径做,节点和连线要精确对位,闸门开合要靠时间轴驱动,正好能试出这套工具的深浅。
| 指标 | 实测值 |
|---|---|
| 全片渲染(1800 帧) | 181 秒 |
| 单帧耗时 | 0.115–0.12 秒 |
| 纯编码(91 帧,ffmpeg 实测) | 0.8 秒 |
| 编码占总流程 | 不到 2% |
| 并发从 2 调到 4 | 0.115 → 0.12,没有提升 |
这组数字回答了一个我原本也想错的问题:该不该用 GPU 渲染。
结论是不该,至少在这条路线上不该。传统剪辑软件导出确实吃硬件编码器,NVENC 能快三五倍,但这套流程里编码只占 2%——1800 帧的编码时间加起来不到 30 秒,而 Chrome 逐帧把网页画出来花了一百五十多秒。瓶颈在浏览器渲染每一帧:解析 DOM、算布局、绘制、截图,这活没法交给 GPU,更没法交给 NPU,因为 NPU 做的是矩阵运算,干不了排版和光栅化。
那并发调高有用吗?实测也没用,0.115 变成 0.12,反而略慢,说明限制不在并行度而在单帧本身的开销。真要提速,方向是减少每帧的复杂度(少用滤镜、少做模糊、控制元素数量),或者分段并行渲染再拼接。
顺带说一个反例:如果场景里用了 WebGL 或者 three.js 做三维,GPU 就有意义了,因为那部分本来就是 GPU 在算。所以"要不要 GPU"取决于内容形态,不是一概而论。
估算时间有个简单公式:帧数 × 0.12 秒,再加四十秒左右的打包开销。所以 30 秒的片子大约两分钟,两分钟的片子就要七分多钟。帧率的影响是线性的,30fps 换 60fps 直接翻倍,而这类"信息传达"的片子 30fps 完全够——观众看的是内容,不是运动模糊的顺滑度。
分辨率倒是可以讲究一下。引擎支持超采样,渲 3840 再缩到 1920,代价是时间翻倍,换来的好处是斜线和细字的边缘更干净。纯文字排版、大量斜线的架构图值得这么做;大面积色块的片子就没必要,压缩之后看不出来。我这条片子全是横竖线和文字,1920 直出已经够,就没开超采样。
音效,以及怎么验证它真的响了
引擎自带两个合成音效,whoosh.wav(转场呼啸)和 impact.wav(撞击),随工程生成,不用下载。素材库里还有一百多个 FLAC 乐器采样,来自 VCSL 采样库,CC0 许可,但那是单音和单次打击,不是整段配乐,不能直接当 BGM 用。
我在四个位置加了音效,然后验了响度:
整体:mean -29.8 dB,max -1.9 dB
0.6s → -1.9 dB 有声
11.3s → -2.0 dB 有声
25.0s → -91.0 dB 静音
33.3s → -2.0 dB 有声
42.0s → -4.6 dB 有声
第二十五秒那个 -91 dB 是最有意思的数字,它证明只有指定的点响了,中间是真的没声音。这种验证靠人耳听根本听不出精确值,而做视频最难自证的一件事,恰恰就是"我以为加上了,其实没加上"——播放器里听着有点动静,你就以为成了,回头一看音轨是空的。
更进一步的做法是拍点绑定:先量出 BGM 的 BPM 和拍点,然后让切镜、动作、音效全部对齐到拍点,容差可以收到 0 到 3 帧。这一步我没做,因为手上没有合适的配乐。有 BGM 的话,这是让成片"听起来专业"的关键,比多加几个音效有用得多——音效不是越多越好,是越准越好。
这套东西的边界
说了这么多优点,得把不能做的写清楚。
能做:示意图、架构图、流程图、数据可视化、界面演示、几何与粒子动效、文字排版动画、三维场景(这块能用 WebGL,GPU 才有意义)、技术讲解动画。
不能做:真实人像、自然风景、写实材质,以及任何需要"了解世界长什么样"的画面。这不是调参能解决的,是能力维度的问题,再多的代码也补不出一个它从没见过的场景。
不适合的场景:把现成素材剪一剪、真人拍摄、需要大量实拍素材的片子。这些用剪辑软件更快,用这套东西反而绕远路。
不过它不排斥后期。输出的是标准 H.264 的 mp4,扔进任何剪辑软件都能接着改;引擎还带一个导出剪映素材包的命令,把时间轴、字幕、音轨拆成工程文件,方便在剪映里再调一遍。字幕也能单独导出 SRT。所以定位是"把画面做到八九成,剩下的交给人",不是"一条龙到发布"。
还有一个现实问题得提前说明,写场景代码这件事本身需要一点前端基础。React 组件、CSS 布局、SVG 路径,这些对没写过网页的人是有门槛的。虽然可以让模型全写,但改起来得能看懂,不然每次调整都得重新描述一遍需求,效率反而不如直接用剪辑软件。
回到那期视频
我最后还是把那期宽带限速的视频骨架做出来了,六段结构,链路图、测速曲线、闸门收窄的示意,181 秒渲完。
但说实话,画面是通用的,不是我的故事。片子里的曲线没有具体数字,闸门没写"联通",时间线也没填日期。原因很简单,这些细节我不能编:速度从多少掉到多少、哪一天发现的、最后找谁解决的,这些得从自己的记录里翻,翻不到就得去问当时的自己。
这是一个挺有意思的落差。工具能把画面做得挺像样,但内容真不真实,取决于你往里填了什么。生成式视频工具会让你觉得"AI 都做完了",这套东西恰恰相反,它把最难的部分(讲什么)全留给你,只解决了次难的部分(怎么画)。
所以下一步不是继续优化画面,是回去翻工单和测速截图。等把真实的数字填进去,这期视频才算能发。
如果你也想做类似的片子,建议先想清楚要讲的那件事有没有"证据"——测速截图、报错、日志、聊天记录都算,哪怕是一张糊掉的手机照片,只要能对上时间点就有用。有证据,这套工具能帮你把证据讲清楚,观众会信;没有证据,它只能帮你做得好看一点,而好看恰恰是最不值钱的那部分,满屏都是。
如果你觉得这篇文章不错,有用的话可以点击下面的“赞赏”支持作者,你的支持是我更新的动力(饿饿吃饭)。


Comments NOTHING