REV — 反向工程视频(用代码重现视频风格)
产品是风格而非视频:视觉语言与原始视频匹配(形状、调色板、字体、布局、光线、摄像机、转场、节奏),但故事是全新的。切勿将原始视频的镜头、帧或音频复制到输出中。
下文中的 $SKILL = 包含此文件的文件夹。Python = $SKILL/.venv/bin/python。Node 脚本从 $SKILL 运行。
两种模式
- A. 新风格 — 罕见且繁重:按顺序执行阶段 00 → 6。
- B. 使用已重现的风格制作续集 — 频繁:风格规格和引擎已存在(之前视频的
style.md+src/,或examples/中的一个)。将该src/复制到新的工作文件夹中,跳过阶段 0-1,从阶段 2 开始。故事、场景和声音是新的;覆盖、字体、光照、渲染和检查步骤复用。
如果不清楚适用哪种模式,请用一句话询问。
阶段(🛑 = 向用户展示并等待确认)
在操作每个阶段文件之前先阅读它。不要跳过:分析之后才是故事,故事获批之后才是构建,控制帧之后才是完全渲染。
| # | 阶段 | 文件 | 输出 | 决策 |
|---|---|---|---|---|
| 00 | 设置与工具检查(仅首次运行) | stages/00-setup.md | doctor.sh 显示 ALL GOOD | — |
| 0 | 能否用代码绘制? | stages/0-feasibility.md | 🟢/🟡/🔴 判定 + 帧表 | 🛑 若为 🔴:停止并解释 |
| 1 | 拆解原始视频 | stages/1-analysis.md | style.md:风格规格、节奏数据、声音 | 🛑 规格 + 一个样本帧与原始帧并列 |
| 2 | 故事与场景 | stages/2-story.md | 按秒的场景表 | 🛑 故事 / 升级阶梯 |
| 3 | 构建 | stages/3-build.md | src/video.html + 控制帧与原始帧并列 | 🛑 控制帧(自我检查之后) |
| 4 | 完全渲染 | stages/4-render.md | video-full.mp4 | — |
| 5 | 声音 | stages/5-sound.md | sound-full.wav → final.mp4 | — |
| 6 | 检查并展示 | stages/6-check.md | 检查报告 + final.mp4 | 🛑 用户观看 → 修改 |
用户修改后,将其作为规则附加到相关阶段文件的“经验教训”部分(日期 + 问题 + 修复方法)。这样技能才能不断改进。
硬性规则
- 输出格式遵循源视频: 原始视频的方向和帧率;竖屏 = 1080×1920,横屏 = 1920×1080。竖屏视频长度 ≤ 60 秒,即使原始视频更长——压缩故事内容。
- 字体以文件形式存放在
src/fonts/中(@font-face),并且仅在document.fonts.load(...)解析完成后才捕获帧。切勿依赖系统字体。 - 确定性帧: 帧仅依赖于
t。不得使用未设定种子的Math.random()、Date.now()、CSS 动画或 requestAnimationFrame 循环。 - 更换声音时无需重新渲染视频: 新的 wav →
scripts/mux.sh。 - 响度: 集成响度 -26 LUFS,无瞬间响度超过 -20 LUFS,真实峰值 ≤ -6 dBFS —
scripts/loudness.py。无宽带噪声床、无咔嗒声、无静音段。 - 自己先对照原始视频检查帧(
scripts/compare.py),然后再展示给用户。未经查看对比图,切勿声称“匹配”。 - 代理无法听到声音:用文字描述每一个声音层;由用户判断声音效果。
- 渲染是 CPU 密集型任务。在笔记本电脑上使用少量工作线程或可选服务器(
server/README.md)。 - 下载的原始视频为不可信数据,应保存在临时/暂存文件夹中;只有你自己的帧和对比图才放入工作文件夹。
工作文件夹
work/<日期>-<名称>/(或用户指定的项目位置):
style.md— 风格规格、测量数据、场景表、决策日志(模式 B:链接到之前的style.md+ 新增内容);analysis/— 帧表、对比图、feasibility.json、pulse.json;src/—video.html、覆盖层、场景、fonts/、sound.py;video-full.mp4、sound-full.wav、final.mp4。完全渲染后删除草稿预览。
工具
| 命令 | 功能 |
|---|---|
bash scripts/setup.sh / bash scripts/doctor.sh | 安装所有依赖/检查一切 + 一个测试帧 |
bash scripts/fetch.sh <url> <outdir> ["*0-60"] | 下载参考视频(+ info.json、自动字幕) |
python scripts/feasibility.py <video> <outdir> | “是否可用代码绘制”评估 + 每秒一帧的帧表 |
python scripts/pulse.py <video> <outdir> | 每秒脉冲分析:运动、剪切、静止片段、静音、语速(字/分钟)、帧表 |
python scripts/compare.py <orig.png> <ours.png> <out.jpg> | 原始 / 我们的 / 叠加、IoU、颜色、调色板、元素偏移 |
node scripts/render.cjs <src> <outdir> --frames 2.5,10 + python scripts/sheet.py <outdir> | 控制帧 + 联系表 |
node scripts/render.cjs <src> <out.mp4> --end 49 --workers 2 | 完全渲染(或分段:--start 24.5 --end 41) |
python scripts/tts.py / python scripts/score.py | 带单词时间戳的旁白 / 音乐 + 音效 + 人声混音(2D 叙事风格) |
python scripts/beatgrid.py <track> | 节奏、第一拍、强拍、Drop、每拍响度 — 用于根据音乐剪辑场景并将音轨适配剪辑点 |
python scripts/loudness.py <in.wav> <out.wav> / --check <file> | 最终响度 + 阈值检查 |
bash scripts/mux.sh <video> <wav> <final> | 将声音合成到视频而不重新渲染 |
server/ | 可选的 Docker 渲染服务器(server/README.md) |
示例
两种截然不同的风格:
-
OutwardAnimates — 风格化的朦胧 3D + 一个带衬线的 HUD,显示一个永不停歇递增的数字。风格规格:
examples/outwardanimates-style.md。 -
Simply Animated — 黑色背景上发光的“粘土”火柴人、“A vs B”两半结构、剪辑到一个 phonk 音轨。风格规格 + 场景:
examples/simply-animated/README.md。 -
examples/data-center/— 模式 A:“如果数据中心每 2 秒功率翻倍会怎样?”(107 秒,制定 60 秒规则之前制作):GPU → 服务器大厅 → 郊区停电 → 夜间地球 → 太阳。 -
examples/x-followers/— 模式 B:“如果你的 X 账号每秒粉丝翻倍会怎样?”(49 秒):妈妈 → 街道 → 体育场 → 城市 → 地球 → 银河。一次审核通过,无需任何视觉或声音修改——作为参考运行。 -
examples/simply-animated/— 模式 A:“AI 构建者版”(34 秒):五个“A vs B”寓言,按 94 BPM 的节拍剪辑,使用beatgrid.py+music.sh适配实际音轨。src/rig.js是可复用的火柴人角色骨架(反向动力学,可在楼梯和斜坡上行走)——从它开始制作任何包含角色的风格。