Communitygithub.com

录制演示视频(免费、脚本化)

当你需要为真实Web应用制作无声的产品演示视频,无需付费工具、手动录屏或人工操作时使用——通过脚本驱动浏览器执行功能并渲染为mp4文件。触发词包括“演示视频”、“功能演示”、“录制应用”、“展示此功能”、“制作导览”,或同时批量制作多个功能演示。适用于Vite/React/Supabase应用(VettedAI + Congrats技术栈);引擎与框架无关。

录制演示视频(免费、脚本化) 是什么?

该技能是一个用于自动化录制Web应用无声演示视频的工具,主要通过Playwright驱动浏览器执行预定义流程并录制屏幕,再通过ffmpeg将录制的.webm文件转换为.mp4视频。它无需依赖任何付费SaaS服务或人工屏幕录制,支持批量生成多个功能演示,同时录制脚本也可作为UX冒烟测试使用。技能适用于Vite/React/Supabase技术栈(VettedAI + Congrats),但引擎本身与框架无关。它会在目标仓库的`demo/`目录下生成一套标准文件(record.mjs、polish.sh、run.sh、README.md),开发者只需修改FLOWS配置即可快速添加新视频。技能还包含了丰富的实践经验,如如何正确通过应用的Supabase客户端进行登录(而非伪造localStorage)、如何配置本地开发服务器指向staging环境、如何处理staging数据schema滞后、以及如何确保视频录制的质量等。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/tobilafinhangit/skill-master/tree/HEAD/.agent/skills/recording-demo-videos

在你喜欢的 AI 中提问

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

文档

录制演示视频(免费、脚本化) 是做什么的?

通过脚本驱动浏览器,为真实应用制作无声的产品演示视频,并渲染为mp4。 免费且完全本地化:Playwright驱动应用,ffmpeg生成视频。无需付费SaaS、无需旁白、无需人工点击。同一个脚本同时可作为UX冒烟测试,当UI变化时可重新渲染——这正是可持续性地制作大量功能演示的关键。

何时使用

  • 用户希望获得一个或多个功能演示/导览视频,但不想为工具付费。
  • 面临“每次新功能都需要有人手动录屏”的重复性问题。
  • 需要快速提供功能端到端工作的可视化证明,且基于真实UI。

不适用于:含有大量动画且带画外音的市场营销视频(应使用专业剪辑工具),或需要真人在镜头前互动的场景。

工作流程

获取登录会话  →  使用Playwright驱动应用(录制为.webm)  →  ffmpeg转换为.mp4

在目标仓库的demo/目录下会生成三个文件(从resources/复制而来):

  • record.mjs — 引擎核心。包含一个CONFIG块(仓库特定配置)和一个FLOWS映射(每个视频对应一个条目)。
  • polish.sh — 将.webm转换为.mp4,修剪登录引导部分,可选添加烧录字幕。
  • run.sh — 一步到位:将开发环境指向staging、录制、后期处理、清理。
  • README.md — 每个仓库的使用说明。

要制作新视频:复制一个FLOWS条目,修改url和steps。这就是完整的操作循环。

设置清单(每个仓库只需执行一次)

  1. 安装工具(一次性):npm install -D @playwright/test && npx playwright install chromium。需要ffmpeg(使用Homebrew安装)。对于烧录字幕,需要安装包含libfreetype的ffmpeg版本;否则字幕会自动跳过,其余功能仍正常工作。
  2. 了解仓库的具体情况,并在record.mjs的CONFIG块中填写:
    • 开发命令 — 应用本地启动方式(通常为npm run dev,有时在子目录如congrats/中)。
    • Supabase客户端模块路径 — 通常为src/integrations/supabase/client.ts。录制器会在页面内导入它以实现登录(参见陷阱1)。
    • 录制所用的数据库 — 使用staging环境,切勿使用生产环境(避免真实用户PII)。需找到其URL、匿名/公开密钥、服务密钥和直接数据库URL。在此组织内,这些信息位于audition仓库的.env.local文件中(VETTED_SUPABASE_*对应VettedAI的staging环境,STAGING_CONGRATS_SUPABASE_*对应Congrats的staging环境)。
    • 登录邮箱 — 一个合成/测试账号,拥有可演示的数据。在获取会话之前始终询问用户使用哪个账号(项目守则:未经允许不得使用真实用户进行测试)。
    • 路由 — 要录制的流程对应的深层链接路径。
  3. 将本地开发服务器指向staging环境(参见陷阱2)。
  4. 编写流程,运行bash demo/run.sh <flow>,并通过提取帧进行验证(陷阱8)。

陷阱(来之不易的经验——调试前请先阅读)

1. 通过应用自身的Supabase客户端登录,而非伪造localStorage

Supabase-js会在浏览器中以其非标准键/信封格式写入会话;直接注入localStorage['sb-<ref>-auth-token'] = JSON.stringify(session)看似正确,但客户端实际上不会读取它——应用会跳转到/login。解决方案:在服务端mint一个会话(使用admin.generateLink → verifyOtp获取access_token和refresh_token,无需密码),然后在页面内import应用的Supabase客户端并调用supabase.auth.setSession({access_token, refresh_token})。这会将正确的数据写入存储,且会话在页面导航期间保持有效。这是最重要的一步。

2. --mode staging可能被静默忽略 → 使用.env.development.local

vite-react-ssg dev(以及某些其他配置)会在加载环境变量文件时忽略--mode,因此.env.staging永远不会被加载,应用仍会指向生产环境(你会看到请求发往生产Supabase主机)。Vite始终会自动加载开发模式下优先级高于.env/.env.local的.env.development.local。因此,run.sh会在录制时将你的staging配置复制到.env.development.local中,并在退出时删除它(否则每次运行npm run dev都将静默指向staging——这是一个真正的隐患)。普通的vite仓库可能会遵循--mode;可通过观察应用调用哪个Supabase主机来测试。

3. Staging schema可能滞后于前端 → 进行针对性的增量修改

Staging分支可能缺少前端需要查询的新列→数据查询返回400错误(“column X does not exist”),导致屏幕渲染为空。不要重放整个数据库迁移。对比前端读取的少数几个表的字段(通过information_schema.columns比较staging和production),然后仅应用缺失的字段作为增量的、可为空的ALTER TABLE ... ADD COLUMN IF NOT EXISTS。需获得用户同意——这是一次staging数据库更改。

4. 种子数据的量级可能不匹配

合成种子数据的分值/值可能与UI格式化器期望的范围不一致(例如,种子数据存储为0-100,而UI使用value/5*100→显示“1392%”)。检查格式化器对应的预期范围与production的真实值对比;必要时重新调整种子数据(需先询问用户——这是一次数据修改)。

5. Playwright录制的视频不显示鼠标光标

通过addInitScript注入一个虚拟光标叠加层(一个跟随鼠标移动并在按下鼠标时放大的圆点)。模板中已包含此功能。在点击前将鼠标移动到真实坐标,以便光标正确跟踪。

6. ffmpeg可能缺少drawtext功能

没有libfreetype支持的ffmpeg在添加烧录字幕时会报错。polish.sh会检测drawtext,如果缺失则跳过字幕——不要让字幕故障阻塞mp4的生成。

7. 自动修剪登录/启动引导部分

录制会捕获登录和应用启动的等待时间(数秒的空白)。record.mjs会测量引导时间并写入一个.trim附属文件;polish.sh会据此进行裁剪(ffmpeg -ss)。

8. 通过帧进行验证,不要仅凭“已录制”来判断

使用ffmpeg -ss <t> -i out.mp4 -frames:v 1 frame.png在几个时间点提取帧并实际查看。最初的几次录制可能会停留在/login页面、骨架屏或错误的标签页——帧是检测这些问题的方法。

9. 数据与认证安全性

在staging环境使用合成数据(例如seed_…@test.vetted.com)进行录制,切勿使用真实客户的项目(避免PII)。始终询问用户要登录哪个账号。创建认证会话是一项实际的操作——需先获得确认。

编写流程

在record.mjs中,FLOWS是一个包含{ label, url, steps(page, ui) }的映射。ui辅助方法涵盖大多数需求:

  • ui.settle(what, [words]) — 等待内容加载完成(networkidle + 一个证明屏幕已加载的关键词)
  • ui.scrollThrough(fraction, steps) — 平滑向下滚动再返回
  • ui.clickFirstCandidate() / 通用形式 ui.clickFirst(selectors) — 尽力点击,绝不硬性失败
  • ui.beat(ms) — 有意的暂停,使视频观看体验更流畅

保持流程中selector的使用轻量化和尽力而为(使用try/catch包裹点击操作),以便某个selector匹配失败时降级为“仍然是好看的滚动演示”而非崩溃。节奏要宽松(800–1800ms的停顿);一个好的无声演示时长通常为15–35秒。

输出与交付

mp4文件位于demo/output/目录中(已加入gitignore)。使用open demo/output/<flow>.mp4播放(相对markdown链接无法在IDE中播放——它会在编辑器中打开文件)。共享路径或为用户执行open命令。

传播此技能(它位于skill-master中)

此技能的规范版本位于submodules/skill-master/.agent/skills/recording-demo-videos/,并通过符号链接到每个仓库的.agent/skills/目录。编辑后,先提交并推送子模块,再更新父仓库的指针,然后运行/distribute-skill以更新同级仓库(在推送前需询问用户)。详见skill-master-submodule-sync规则。

相关技能