Communitygithub.com

demo-video

使用 Playwright 和 Edge TTS 录制真实 Web 应用工作流(注册、创建订单、提交工单...)的带有解说和字幕的演示视频,真 1920x1080 分辨率,显示光标和红色高亮框。当被要求“为 <流程> 创建演示/演示视频/操作演示视频”时,或在屏幕改变后重新制作演示,或更改演示的解说、语音或速度时使用。

demo-video 是什么?

demo-video 是一个 AI 代理技能,用于自动生成真实 Web 应用流程的高质量演示视频。它使用 Playwright 在一个全新的无头浏览器中执行真实操作,通过 Edge TTS 生成语音解说,并嵌入字幕,最终渲染为 1920x1080 的 MP4 文件。该技能支持创建新演示、在应用 UI 变化后重新录制、调整语速/语音/解说词,以及添加可视化高亮框。它适用于 Claude Code、Cursor 等 AI 代理环境,要求 Node 18+ 和 Chrome/Edge 浏览器。整个工作流包括初始化、干运行、编写解说和操作脚本、录制、渲染和验证等步骤,并确保视频中无解说空白段超过 7 秒。

兼容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/Thaksen-Karote/demo-video-kit/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

演示视频

在全新的无头浏览器中录制真实应用(绝不使用模拟或旧视频),使用 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 步:剪辑时长决定屏幕上的时间,因此视频始终会重新录制

规则(始终遵守)

  1. 真实且全新。 新的浏览器会话;真实的应用;真实的数据。绝不要伪造结果、数字或状态;仅当应用显示成功后宣布成功。
  2. 安全。 仅限本地或测试环境:每次运行确实会创建流程所需的内容。绝不打印或存储凭据:凭据来自环境变量(例如 DEMO_EMAIL、DEMO_PASSWORD);密码仅显示为点号。如果不知道测试账号则询问。
  3. 画面。 1920x1080,16:9,30 fps,H.264 + AAC MP4,无头录制以确保无内容被裁剪。可见光标平稳滑向每个目标并有轻触点击光圈;无缩放、无镜头移动、无花哨转场。对任何元素操作前,先将其完全滚动到视图中;从上到下缓慢阅读长页面,速度要足以阅读。
  4. 声音。 Edge TTS,默认语音 en-IN-NeerjaNeural(使用 <kit> voices en- 或其他过滤器列出更多语音)。每个解说段落对应一个音频片段;片段从不重叠;解说只描述屏幕上正在发生或即将在该场景发生的事情。
  5. 无超过 7 秒的空白。 没有解说的时长不能达到 7 秒。当录制器发出警告,或 verify.py 失败时,延长或拆分该段落的解说,或加快其操作速度,然后重新录制。
  6. 节奏。 不要匆忙:输入的每个值必须在继续之前可见。
  7. 跟随应用。 从运行的应用(干运行)中获取路由、标签和按钮名称,绝不依赖记忆。按钮的名称与应用显示一致。
  8. 输出不要提交到 git。 除非被要求,否则生成的音频、构建文件和 MP4 不提交。
  9. 高亮。 每个演示都会用红色框标记解说所指的元素,除非请求说“不要高亮”。

高亮

一个红色框(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 事后绘制框。这是备用方案;重新录制更简单也更准确。

工作流

  1. 设置。 运行 <kit> doctor(参见设置)并检查应用能否从其 URL 访问。
  2. 干运行。 使用 Playwright 浏览器工具,在不录制且不执行最终提交的情况下走一遍真实流程:记录每个屏幕的路由、标签和 getByRole 名称、下拉选项、对话框、最终按钮以及点击后的结果。
  3. 编写演示: <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。
  4. 生成。 <kit> run <演示目录>(环境变量中设置 DEMO_BASE_URL 和凭据)将依次执行音频、录制、渲染和验证。录制器输出的每行 WARNING 以及验证器输出的每行 FAIL 都违反了规则 5:需要修复并重新运行。如果只修改了 flow.cjs,使用 --from record 跳过音频步骤;如果只修改了字幕或编码,使用 --from render 跳过录制步骤。
  5. 检查结果。 build/check/contact-sheet.png:每一帧都显示完整屏幕、光标、正确的步骤、可读的字幕以及解说所提及元素上的框。视频位于 <演示目录>/<文件夹名>.mp4。
  6. 交付。 报告 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=../..)加框

相关技能