知识库原理约 11 分钟

代码做视频:四个技能实测与分场景选型 ​

一句话答案:代码做视频不是「让模型生成像素」,而是「让模型写一段程序,这段程序在每一帧算出一个画面,再把帧拼成 MP4」。所以它的产物可复现、可编辑、文字永远清晰——代价是你得先准备好素材(截图、文案、配音),并且第一次配环境要花点时间。本文实测了四个开源技能,按场景告诉你该用哪个、开拍前要准备什么。

什么是代码做视频,和文生视频差在哪 ​

结论:两者是两条完全不同的路线。文生视频是模型逐帧生成像素,适合实拍质感、人物表演;代码做视频是每一帧由你写的程序算出来,适合字幕条、数据动画、代码演示、产品宣传片、科普讲解。

最关键的一条差别是可复现。同一份代码渲染一百次,结果完全一样;你改一行文案重渲,只有受影响的部分变。生成式视频做不到这点——同样输入两次,可能给出不同结果。

做法谁在画适合不适合
文生视频模型生成像素实拍质感、人物表演文字多的画面、长镜头
代码做视频你和 Claude 写的代码字幕条、数据动画、logo 演绎、代码演示、产品宣传片、科普讲解照片级真实人物

四个技能的场景分工 ​

结论:没有哪个技能是万能的。选型只看一件事——你要做的片子里,信息是怎么组织的。

场景推荐技能stars一句话理由
产品宣传片、发布片video-shotcraft11553152 张镜头配方卡,每张写明何时用、时序、缓动、已知坑,直接对着挑
科普讲解(黑板风 MG)anything2explainer2449主题进、解说视频出,字幕、章节进度条、HUD 全套现成,QC 判据都成文了
口播教程(配音驱动)video-talkcraft1535配音是输入不是产出,字级时间戳锁住画面动效,适合「讲步骤」
纯代码动效、不用 Remotionclaude-motion-design484seek(t) 纯函数引擎 + Playwright 逐帧渲染,不依赖 Remotion 授权

四者技术路线有重叠也有差异:前三个都是 Remotion(React)路线,第四个是 HTML + Playwright 路线。这一条本身就是选型理由——如果你想避开 Remotion 的许可与版本约束,第四个是现成出路。

开拍前要准备什么 ​

结论:四个技能里有三个的产物质量,直接取决于你给的素材质量。素材不到位,再好的技能也救不回来。

素材什么时候要怎么拿
真实页面截图宣传片、界面演示无头浏览器 1920 视口截图,2 倍像素密度
终端录屏讲操作的教程跑一遍真实命令再录,不要摆拍
口播稿科普、教程先写稿再配音,不要边配边改稿
配音文件口播类必备见下方「配音专区」
品牌 token全部从你产品自己的 CSS 变量里抄颜色和字体

配音是最容易被低估的一项。 本文实测下来,四个技能里有三个把配音当成硬约束——没有时间戳就不出片,因为字幕和动效都要靠它对齐。

配音专区:两条路线 ​

结论:中文配音有两条可行路线,按你能不能连外网选。

路线音色优点前提
Kokoro-82M-v1.1-zh(本地)四个中文音色免费、可商用、不联网、模型只有 82Mpip install kokoro misaki[zh] soundfile,中文音色要设 lang_code='z'
edge-tts(云端)十几个中文音色音质自然,有词级边界,字幕节拍最准需要能连 speech.platform.bing.com;连不上就握手 403

实测提醒:很多人 edge-tts 一装上就发现连不上。这不是配置问题,是网络问题——本文测试机直连被拒,系统代理端口也没在跑。如果你的机器同样情况,直接上 Kokoro。代价是 Kokoro 没有词边界,只能「逐块合成」,块起始帧仍然精确,但块界断句略生硬。

术语验读是必做项。MCP 念「M C P」还是别的、模型 ID 怎么读、.json 念不念「点 json」,都得单独试听定,不能想当然。

混音规范 ​

项数值
人声整体响度-14 LUFS
音乐压到 -18 LUFS 以下给人声让位
峰值不超过 -1 dBTS

工具就一条 ffmpeg:ffmpeg -af loudnorm=I=-14:TP=-1.5:LRA=11。

四支样片 ​

以下四支都是本机真实渲染产出,不是概念图。

1. 无限卡宣传片(video-shotcraft 方法论) ​

规格:31.9 秒 · 1920×1080 · 30fps

用了什么:真实官网首页截图做 2.5D 运镜、三档套餐卡从官网配置数据取真文案、终端逐行打出、代码合成配乐 + 五处钉帧音效。

开拍前要准备:官网首页 2 倍截图、档位名称与价格的真实文案、官网 SVG logo。

2. 上下文窗口 + 提示缓存(anything2explainer) ​

规格:41.7 秒 · 1280×720 · 30fps(本片按 a2e 自身标准声明静止上限 3.0 秒)

用了什么:黑底白线稿 + 紫点缀的固定视觉体系,Kokoro 配音(5.19 字/秒),逐块对齐字幕,底部章节进度条。两个主题(上下文窗口、提示缓存)并进一支,各占一章。

开拍前要准备:解说稿(先定稿)、Kokoro 中文音色选定、幕底选型(点阵波或星点)。

3. MCP 是什么(video-talkcraft) ​

规格:36.0 秒 · 1920×1080 · 30fps

用了什么:五镜结构(终端 → 装手脚 → 能干什么 → 怎么装 → 装完什么样),句级时间戳锁动效,深空蓝主题。

开拍前要准备:配音成品与时间戳 JSON、脱敏后的配置示例、每镜的语义标注(这句在做什么)。

4. Skills 是什么(video-talkcraft) ​

规格:43.3 秒 · 1920×1080 · 30fps

同样五镜结构,把 MCP 那套换成了「技能目录 → 文件夹即技能 → 放进目录自动认出 → 下次照做」。

5. 一条视频是怎么算出来的(Remotion 重做版) ​

规格:41.0 秒 · 1920×1080 · 30fps

这条本身就是在讲这门技术。第一版我们用 claude-motion-design 的 seek(t) 引擎做,四支镜头全是并列的示意图,看不出因果关系,而且零解说零字幕——观众没有进入点。第三轮推倒重做,换成 Remotion,五镜改成一条完整因果链:写脚本 → 脚本切成时间轴 → 每一秒交给函数算一帧 → 一帧帧接成视频 → 改一句重渲。

开拍前要准备:先定稿解说词(它是唯一真源,画面按句切)、每个元素锚到具体的字(tSay)、标题前 5 帧给完成态构图。

怎么按自己的场景选 ​

结论:三步就能定下来。

  1. 数一下片子里要出现几段解说。有配音、需要字级对齐 → 走 video-talkcraft。只有字幕或纯画面 → 跳过这步。
  2. 看画面是「抽象示意图」还是「真实界面」。真实界面(你的产品、你的终端)→ video-shotcraft,它整套方法论围绕「先起服务再截图」;抽象示意图 → anything2explainer 或 talkcraft,它们更适合画概念。
  3. 看你要不要避开 Remotion。要 → claude-motion-design,它自带完整引擎。不要 → 前三个随便挑,都成熟。

只有一种情况建议自己写:片子要同时有真实界面和抽象示意(比如先演示一遍真实产品,再用抽象图解释原理)。这时用 video-shotcraft 的方法论但自己搭工程,比硬套任何一个技能都顺。

用户只需要给什么 ​

结论:五个样片做了两轮,最容易走偏的就是这件事——把技能该做的设计当成需求写进去。用户给方向,技能做设计。

该给(五样)不该给
主题或产品入口分镜表、镜头时长
时长(3 分钟以内单章,3–5 分钟 3–4 章)每个元素的出现帧号
要不要解说(要 / 不要)字幕位置、字号、安全区
配音偏好(没有就用默认)逐元素的 tSay 锚点
素材路径(截图、录屏、产品页面)运镜曲线、缓动参数、动效配方卡编号

为什么不该给:这些是技能的内部实现。talkcraft 的 tSay()、a2e 的 GLITCH_SEQ、shotcraft 的镜头卡都是技能自己按时间轴和语义段落推导的。你手填的版本会和技能的自动设计冲突——第一轮我手填字幕位置,结果和字幕组件的默认位置打架。

正确的协作方式:需求只给方向,让技能先出 30 秒样片;样片确认后再提具体修改意见,而不是在需求阶段就把实现细节写死。

机器闸:人眼审片会漏,断言不会 ​

第一轮我人工审了帧,认为 V4/V5 通过。实际上那两支片子的场景根本没挂载成片——上部区域像素标准差是 0.00,整片只有字幕。原因是调用 sceneFrameRanges() 时少传了参数,返回 undefined,五个场景全被 if (!r) return null 拦掉。

这类问题靠人眼和静帧都看不出来。 当时我抽的是静帧,静帧里场景是正常的(因为那是从 Remotion 直接渲的单帧),只有合成后的视频才暴露。

第二轮加的七道闸在出片后一条命令跑完,退出码非 0 即不出片:

bash
python scripts/gates/run_all.py outputs/your_video.mp4
python scripts/gates/run_all.py outputs/explainer.mp4 --motion-std=3.0   # a2e 风格片

七道闸分别是:场景挂载、动画密度、布局侵占、解说一致性、响度、首帧完整度、音轨非空。其中最该先上的是第一道——它拦住的是最贵的一类错误(整片渲染白费)。

三轮迭代实录 ​

这是本文最想讲的一件事:同一批样片,我们迭代了三轮,每轮都有明确的输入、明确的发现、明确的改动。 下面按真实经过写,不美化。

第一轮:给了什么,发现了什么 ​

输入:一个主题、五句解说词、一张官网截图。

结果:五支片子全部渲染出来了,但三支有硬伤——V4/V5 的成片是纯色底加字幕(场景根本没挂载),V1 没有解说,我抽静帧审片却认为「画面正确」。

为什么没发现:静帧是从 Remotion 直接渲的单帧,场景是正常的;只有合成后的视频才暴露。而我看 V5 时工作目录漂移到了 V6,把 V4 的帧当 V5 的看了。

第二轮:补齐流程,加机器闸 ​

输入:同上的内容,加上语义标注 + SHOTBOOK + shots.json,以及一套七道机器闸。

为什么这次不一样:a2e 和 talkcraft 都要求先产出这几个中间文件,我第一轮跳过了。而且两个技能都自带质检脚本(talkcraft 的 preflight.py 会在渲染前拦语义覆盖,freeze_probe.py 会预判静止段),我一次都没跑。

改动与效果:

指标第一轮第二轮
V4/V5 上部像素标准差0.00(场景没挂载)92.18 / 92.58
V4/V5 最长静止23.0s / 27.25s(全片)0.00s
V1 有无解说无已补 28.8 秒
V2 首帧纯黑正常

但第二轮自己也有盲区:七道闸能验「场景挂没挂」「动没动」「字有没有压字幕」,验不了「排版挤不挤得下」——V1 的卡片文字实际超出 122px,七道闸全过,肉眼能看出来,我们却漏了。

第三轮:加排版守卫,V6 推倒重做 ​

输入:同上的内容,加上排版预算守卫。

改动:

  1. V1 卡片:卖点文案从 19–31 字缩到 8–10 字,卡片高度 400→460,价格字号 72→66。排版守卫实测从「超 122.3px」变成「余量 46.1px」。
  2. V1 尾部:修掉一个此前完全没发现的问题——CTA 的入场帧是 214,而 Sequence 只有 215 帧,永远等不到;加上总时长多出 100 帧,尾部 3.5 秒实测是纯白(std=0.000)。改成收尾层按绝对帧常驻。
  3. V6 推倒重做:从 seek(t) 引擎换成 Remotion,五镜改成一条完整因果链。
  4. V4/V5 加长:解说从 5 句加到 10 句,字级锚点从每镜 0–2 处补到 2–3 处。

机器闸是怎么一步步长出来的 ​

七道闸不是一开始设计好的,是被每一轮的问题逼出来的:

闸为什么会加它
g0_scene_mounted第一轮 V4/V5 场景没挂载成片,人眼和静帧都没看出来
g3_vo第一轮 V1 干脆没有解说
g5_first_frame第二轮 V2 首帧是全黑,而平台抓第一帧当封面
g3_layout_fit第二轮 V1 卡片文字溢出,七道闸全过却肉眼可见

这条才是本文真正想教的方法:不是「记住七个阈值」,而是每次肉眼发现一个质量问题,就把它变成一条断言。第三轮我们加排版守卫时还踩了一个坑——守卫里的文案引用解析失败被 or [] 静默吞掉,导致卖点完全没算进去,守卫报「PASS 余量 110px」,而手算是「超 122px」。漏算还报 PASS 是最坏的形态,比报错危险得多。

踩坑清单(实测) ​

结论:以下每一条都是本文四支片子真实撞到的,照着避。

坑现象解法
TypeScript 版本npm i -D typescript 装到 TS 7,Remotion 报 Cannot read properties of undefined (reading 'readFile')钉 [email protected]
图片引用<Img src="home.png"> 404必须 staticFile('assets/home.png')
文件后缀镜头组件写成 .ts,TS 报一堆 '>' expected镜头文件一律 .tsx
edge-tts 连不上WebSocket 握手 403开代理,或改用 Kokoro
motion-design 页面卡住window.ready 永不置位引擎默认预载 11 个 logo + Geist 字体,缺了就 404 阻塞 fonts.ready;删掉预载改系统字体
渲染脚本硬编码渲染脚本里的 URL、时长、输出名是原片常量逐个改
首帧空白前几帧淡入,第一帧被平台抓去当封面时是一片底色前 5 帧直接给完成态构图

最后一条值得单独强调:第一帧必须是完整画面。X、Threads 这类平台会直接抓视频第一帧当缩略图,第一帧是空白底色或半截入场动画,热度和点击都会打折。

质检怎么做 ​

结论:自动检查能证明结构一致,但视觉和听感必须自己看。两件事都要做。

自动检查用 ffmpeg 就够,本文用的判据:

bash
# 首帧是不是完整画面(唯一灰度值越多,内容越完整)
ffprobe -v error -select_streams v -show_frames -show_entries frame=pkt_pts_time \
  -of csv outputs/your_video.mp4 | head -1

# 整体响度
ffmpeg -hide_banner -i your.mp4 -af "loudnorm=I=-14:TP=-1:LRA=11:print_format=json" -f null -

人工审片看三样:抽 1fps 联系表逐帧过一遍找穿帮、每个转场前后各看一帧确认没有半帧断、完整试听一遍确认音乐没盖人声。自动检查全绿但没人看过的情况,本文在结果文档里都如实标注了。