演示视频
在全新的无头浏览器中录制真实应用(绝不使用模拟或旧视频),使用 Edge TTS 添加解说,嵌入字幕,并渲染为 MP4。一个演示包含两个为流程编写的文件:narration.json 和 flow.cjs;其余部分由本文件夹中的 demo-video-kit 命令处理。工作示例位于 examples/todomvc/。
下面 <kit> 表示 node <此文件夹>/bin/demo-video-kit.js(此文件夹例如是 ~/.claude/skills/demo-video);当用户的项目安装了该工具包后,npx demo-video-kit 执行相同操作。<kit> help 列出所有命令。
请求决定任务
| 请求 | 操作 |
|---|---|
| “为 <流程> 创建演示” | 在用户项目的 demos/<流程>/ 目录中执行下面的完整工作流 |
| “<流程> 屏幕已改变,重新制作演示” | 干运行新屏幕(第 2 步),修正 flow.cjs,如果文字不再匹配则修正 narration.json;然后执行第 4 到 8 步 |
| “为现有 <流程> 视频添加高亮框”(不重新录制) | 在运行的应用中测量框的位置,编写 annotations.json,运行 <kit> annotate <演示目录>(参见高亮部分) |
| “...不要高亮” | 省略所有 highlight 选项;其他不变 |
| “更改语音/速度/措辞” | 编辑 narration.json(voice、rate、段落的 text),然后执行第 4 到 8 步:剪辑时长决定屏幕上的时间,因此视频始终会重新录制 |
规则(始终遵守)
- 真实且全新。 新的浏览器会话;真实的应用;真实的数据。绝不要伪造结果、数字或状态;仅当应用显示成功后宣布成功。
- 安全。 仅限本地或测试环境:每次运行确实会创建流程所需的内容。绝不打印或存储凭据:凭据来自环境变量(例如
DEMO_EMAIL、DEMO_PASSWORD);密码仅显示为点号。如果不知道测试账号则询问。 - 画面。 1920x1080,16:9,30 fps,H.264 + AAC MP4,无头录制以确保无内容被裁剪。可见光标平稳滑向每个目标并有轻触点击光圈;无缩放、无镜头移动、无花哨转场。对任何元素操作前,先将其完全滚动到视图中;从上到下缓慢阅读长页面,速度要足以阅读。
- 声音。 Edge TTS,默认语音
en-IN-NeerjaNeural(使用<kit> voices en-或其他过滤器列出更多语音)。每个解说段落对应一个音频片段;片段从不重叠;解说只描述屏幕上正在发生或即将在该场景发生的事情。 - 无超过 7 秒的空白。 没有解说的时长不能达到 7 秒。当录制器发出警告,或
verify.py失败时,延长或拆分该段落的解说,或加快其操作速度,然后重新录制。 - 节奏。 不要匆忙:输入的每个值必须在继续之前可见。
- 跟随应用。 从运行的应用(干运行)中获取路由、标签和按钮名称,绝不依赖记忆。按钮的名称与应用显示一致。
- 输出不要提交到 git。 除非被要求,否则生成的音频、构建文件和 MP4 不提交。
- 高亮。 每个演示都会用红色框标记解说所指的元素,除非请求说“不要高亮”。
高亮
一个红色框(4 px,#E11D48,距离元素 6 px 间隔)在视频录制时实时绘制在页面中,因此它能跟随滚动并成为画面的一部分。默认添加高亮的元素:导航到目标屏幕过程中点击的每个菜单项、启动流程的按钮、审核页面中输入的每块数据以及最后的提交按钮。不要对每个正在输入的字段都加框:光标和输入本身已经显示。
flow.cjs 中的 API:
goto / click / type / pick (loc, ..., { highlight }):highlight: true为光标移到的元素加框;highlight: <定位器>则为另一个元素加框(例如它的整行或整块)。- 框会一直保留,直到光标移到下一个目标。
{ keep: true }同时保留当前框;k.clearHighlights()移除它们;k.highlight(loc)在不移动光标的情况下添加一个框。 - 每个框会向
build/timeline-raw.json中的marks添加一个highlight条目。
对于已录制但未加框的视频,使用 <kit> annotate <演示目录> 根据 annotations.json 事后绘制框。这是备用方案;重新录制更简单也更准确。
工作流
- 设置。 运行
<kit> doctor(参见设置)并检查应用能否从其 URL 访问。 - 干运行。 使用 Playwright 浏览器工具,在不录制且不执行最终提交的情况下走一遍真实流程:记录每个屏幕的路由、标签和
getByRole名称、下拉选项、对话框、最终按钮以及点击后的结果。 - 编写演示:
<kit> init <演示目录> --url <应用 url>可生成一个可直接运行的起始文件;或复制examples/todomvc/。然后编辑:narration.json:标题、语音、语速、pronounce(书写形式 → 口语形式)以及段落{id, scene, text}。如果一个场景的操作耗时较长,将其拆分为多个段落,使每个段落的解说时长大致等于其操作的时长。flow.cjs:runDemo(__dirname, async (k) => { ... }),其中包含与解说段落一一对应的k.segment(id, async (at, clip) => { ... })。使用k.click / k.type / k.pick / k.goto / k.scrollBy;at(seconds)等待到剪辑中的某个时间点(例如clip.cues[0].end)。等待元素,不要等待“network idle”。返回已验证的内容。保留require(process.env.DEMO_KIT || 'demo-video-kit'):命令会设置DEMO_KIT。
- 生成。
<kit> run <演示目录>(环境变量中设置DEMO_BASE_URL和凭据)将依次执行音频、录制、渲染和验证。录制器输出的每行WARNING以及验证器输出的每行FAIL都违反了规则 5:需要修复并重新运行。如果只修改了flow.cjs,使用--from record跳过音频步骤;如果只修改了字幕或编码,使用--from render跳过录制步骤。 - 检查结果。
build/check/contact-sheet.png:每一帧都显示完整屏幕、光标、正确的步骤、可读的字幕以及解说所提及元素上的框。视频位于<演示目录>/<文件夹名>.mp4。 - 交付。 报告 MP4 路径、时长、格式、最长空白段、运行创建的内容以及任何因应用实际工作方式与请求不一致之处。
设置
Node 18+ 和 Google Chrome(或 Microsoft Edge:录制器会自动回退到它,也可以设置 DEMO_BROWSER=msedge)。在此文件夹中运行一次 npm install;语音(msedge-tts)、ffmpeg(ffmpeg-static)和 playwright-core 都会随安装带来,录制器在首次运行时还会获取 Playwright 自带的少量 ffmpeg。<kit> doctor 会检查所有内容,包括语音需要的互联网连接。
已知陷阱
| 陷阱 | 避免方法 |
|---|---|
| 灰色条带,页面底部被截断 | 绝不要在可见的浏览器窗口中录制;demo-kit.cjs 以 1920x1080 无头录制 |
waitForLoadState('networkidle') 在轮询的应用上挂起 | 改为等待元素 |
| 无头 UI 对话框报告为隐藏 | 等待对话框内的字段,而不是对话框本身 |
| 下拉菜单内的 Escape 键关闭整个对话框 | 选择选项,而不是按 Escape |
| 输入多个字段时出现安静空白段 | 拆分该段落的解说;type() 接受 { delay }(默认 32 毫秒) |
| CSS 以大写形式显示的标签 | 匹配实际文本,而不是显示的大小写 |
| 框只圈住了标签本身,而不是其块 | 为标签的父元素(xpath=..)或祖父元素(xpath=../..)加框 |