demo-reel 是做什么的?
您自己制作整个视频:用户提供产品并说明要展示的内容,然后返回一个可以发布的 MP4。屏幕上的所有内容都是真实产品,实时录制;后期处理(窗口边框、摄像机移动、字幕、标题卡和结束卡)在录制后添加。
流程,以及每个步骤生成的文件:
| 步骤 | 命令 | 生成文件 |
|---|---|---|
| 1. 故事板 | 您与用户共同完成 | 3-5 个功能,每个带一条字幕 |
| 2. 场景脚本 | 编写 scenario.mjs | 用户可能采取的步骤 |
| 3. 录制 | bin/reel take scenario.mjs takes/take1 | take1.mov(画面 + 应用声音)、take1.json(事件、元素位置) |
| 4. 编辑 | 编写 edit.json | 场景、镜头、字幕、品牌信息 |
| 5. 预览帧 | bin/reel check edit.json、bin/reel layers edit.json、然后 bin/reel stills edit.json 1,4,9 | 提前发现问题;预览帧 |
| 6. 字幕 | bin/reel subtitles edit.json、然后阅读并修复 build/subtitles.srt | 所说的内容,作为字幕 |
| 7. 渲染 | bin/reel render edit.json renders/x.mp4 --format all | 每种格式的视频及其对应的 .srt 文件 |
| 8. 检查 | bin/reel sheet renders/x.mp4 1,4,9,… | 接触印片、时长、响度 |
examples/sawt/ 是一个完整的工作示例(一个朗读文章的 Chrome 扩展)。在编写自己的脚本之前,请先打开其 scenario.mjs 和 edit.json 文件。docs/edit-format.md 是编辑文件参考;docs/lessons.md 列出了初次使用时可能遇到的问题,因此请在录制前阅读。
0. 设置(一次性)
首先运行 bin/reel doctor:它会检查所有工具和权限,并告知需要修复的内容。bin/reel setup 构建录制器(Swift、ScreenCaptureKit),安装 playwright-core 和用于测试的 Chrome。此外还需:ffmpeg、uv、Google Chrome(用于渲染覆盖层)。运行您的终端需要 屏幕和系统音频录制 权限(系统设置 → 隐私与安全性);如果录制器报告未获得权限,请请求用户授予权限并重新启动终端。
1. 故事板
在开始录制之前,简要达成以下共识:
- 功能按顺序列出,每个功能带一个字幕:一个简短的引子(“单词缩放”)和一个最多两行的标题,其中用
<b>标出核心价值(“跟随朗读。每个单词在朗读时放大。”); - 用于演示的真实内容:一个公共页面、一个示例账户或种子数据。选择能展示功能最佳效果的内容,并确保内容有效(对于 Sawt:选择一个包含难词卡的文章,且站点在列旁有足够空间放置卡片);
- 品牌信息:强调色、浅色变体、背景色调、Logo;标题卡和结束卡文本。
默认格式:1080×1350(4:5),时长 25-35 秒——这种格式在手机信息流中占用空间最大,而且大多数人会静音观看,因此字幕必须独立传达故事。询问视频将在哪里发布:1:1、9:16 和 16:9 都可以从同一个编辑文件生成(--format),因此可以提供这些选项。检查每种格式的预览帧:在 4:5 下构图良好的镜头可能会在 1:1 下裁剪掉标题;按格式微调镜头("1:1": {"dy": 20})。
当产品有声音(或录制时有旁白)时,制作字幕:reel subtitles,然后阅读 .srt 文件,在渲染前修正名称和术语——转录效果不错,但并非完美。将难词放入 subtitles.words 中来引导转录。
2. 场景脚本
场景脚本是一个 ES 模块(完整 API 见 drive/take.mjs):
export const config = { url: "https://…", width: 1700, height: 1090, extension: "./ext" };
export async function setup(api) { /* 设置、登录;api.rect("title", "h1") 用于摄像机目标 */ }
export async function run(api) { /* 演示;在每个需要剪辑的时刻调用 api.mark("step") */ }
export async function after(api) { /* 作为图像场景显示的静态帧,例如放大 3 倍的弹出框 */ }
- 在每个需要剪辑或移动摄像机的时刻标记(
api.mark("sentence", {n}))。编辑会锚定到这些标记,因此即使录制运行速度不同,仍能在正确位置剪接。 - 用
api.rect(name, selector | fn, arg)记录摄像机目标,单位为视口像素。封闭 Shadow DOM 中的元素无法测量:计算它们的位置(参见 Sawt 卡片示例)。 - 点击驱动的产品需要可见的指针。 自动化不会移动真实光标,因此形状会自行显示,按钮会自行按下。在
setup中调用api.pointer.show(),然后使用api.pointer.click(selector | [x, y])、.drag(from, to)、.move(x, y)、.type(text)和.key(k)进行驱动:页面上的箭头会跟随,点击会产生涟漪,移动是缓动的,打字具有人类节奏。通过选择器(title或aria-label通常稳定)控制点击,其位置来自页面。 - 画布内容(绘图、图表、地图)没有可测量的元素:使用
api.rect(name, {x, y, width, height})以 CSS 像素记录您绘制内容的区域。 - Chrome 扩展:通过
api.inWorker(fn)运行扩展自身的代码。依赖activeTab的扩展需要带有主机访问权限的录制副本,因为自动化无法按下浏览器的快捷键(参见examples/sawt/prepare.sh)。不要更改用户看到的任何内容。 - 弹出窗口和其他小型 UI:在
after()中通过 CDP 以设备缩放因子 3 捕获(参见示例),并以图像场景形式展示。通过点击真实控件来捕获切换开关的两种状态,而不是重新加载页面。
运行脚本,然后在编辑前查看录制内容:ffmpeg -ss 6 -i takes/take1.mov -frames:v 1 x.png 并检查 PNG 文件。确认页面样式正确、功能已触发、没有遮挡内容。可随时重新录制——一个录制片段只需一分钟。
3. 编辑
编写 edit.json(参考:docs/edit-format.md)。使其看起来专业而非随意录制的规则:
- 在停顿处剪辑。
bin/reel speech take1.mov列出有声音的位置;片段起始于某一步骤即将开始前,结束于下一步骤开始前。将剪辑锚定到标记:"sentence#5-0.15"。 - 并排内容不适合窄窗口。 左侧的工具栏和右侧的图表可能需要比 4:5 窗口能展示的更宽;
reel check会按格式警告镜头损失的内容。减少并排显示的内容,或为该格式微调镜头。 - 基于矩形区域的镜头。
{"fit": ["title", {"rect": "card1", "dh": 330}], "pad": 60}。先用一个宽的全景镜头,然后推近到字幕所讲述的内容。保持输出中文本至少约 20 像素高;宽镜头可以暂时较小,但不能长时间。 - 每个场景一个字幕,在场景期间持续显示;仅在摄像机移动时切换字幕。
- 让移动有呼吸感: 每次摄像机移动 1.0-1.5 秒,移动结束后至少保持 1.5 秒。
- 标题卡 2-2.5 秒,结束卡 3-3.5 秒。图像场景(弹出窗口、设置面板)3-4 秒。
速度
一个 30 秒的 4:5 渲染在 6 核笔记本电脑上大约需要 3 分钟:帧以并行块形式渲染(默认 4 块;--jobs N),无需重新编码即可拼接,未更改的图层会被重用。在编辑尚未确定时,使用 reel render … --draft(15 fps,快速编码器,大约一半时间)和 reel stills;在预览帧看起来正确后再进行最终渲染。
4. 每次检查
- 在每个场景的开始、中间和结束处,以及每次摄像机移动时,运行
bin/reel layers和bin/reel stills。检查每个 PNG。注意:帧边缘被裁剪的文本或 UI、顶部半隐藏的标题、字幕遮挡重要内容、或完全是空白页面的帧。 - 渲染完成后,对整个视频运行
bin/reel sheet并检查。 - 时长应符合您的计划;当产品有声音时,响度约为 −16 LUFS。
- 同步:屏幕上某一步骤出现的时间点与相应声音开始的时间点应与录制内容匹配。
然后将 MP4 交给用户,附上缩略图(build/layers/title.png),并明确说明哪些是真实的,哪些是为录制而更改的。
音乐
默认情况下,系统会选择适合视频的背景音乐(docs/music.md):它会分析视频(时长、语音、节奏、字幕词汇),评估授权器乐候选曲目——用户的 music/ 文件夹、内置 CC0 库(library/),只有在本地没有合适曲目时才在线搜索——根据测量的节奏、能量和稳定性进行排名,并保留最佳曲目。运行 reel music auto edit.json --audition renders/x.mp4 查看排名并预览最佳曲目。您无法听到,因此在宣布视频完成前,将预览文件交给用户。当最佳曲目仅提供链接(网站阻止脚本化下载)时,将链接提供给用户;用户下载后运行 reel music add <file> --candidate N。如果用户自带曲目,使用 reel music add 记录其许可证并将其放入编辑文件中。始终在渲染文件旁边提供 .credits.txt 文件,并在许可证要求时告知用户需要发布致谢。
限制
- 录制仅支持 macOS(ScreenCaptureKit)。合成和图层渲染可在任何平台运行。
- 目前仅支持浏览器产品;桌面应用需要其自己的驱动程序(辅助功能脚本),但录制器(
--app <bundle id>)和之后的所有步骤已可用于任何应用。 - 生成音乐(
reel music generate)需要接入本地模型;建议使用 ACE-Step,但尚未在 demo-reel 中测试。