Communitygithub.com

旁白版A/B视频

为PR或功能创建带旁白的A/B对比视频:使用Playwright录制每个版本的浏览器运行(包含时间标记、用于动态输入如OTP码的钩子),渲染标题/证据卡片和A/B角标,利用macOS say语音为每个片段配音,加速模型等待时间,冻结最后一帧以匹配旁白时长,最后合成一个MP4文件。

B视频 是什么?

该技能用于自动生成带旁白的A/B对比演示视频。它通过Playwright分别录制两个场景(如基线和实验版本)的浏览器操作,生成包含标题卡片、证据卡片和最终裁决卡片的视频,并利用macOS内置的`say`命令或ElevenLabs API为每个片段添加语音解说。技能会加速模型等待时间(默认10倍速),并在旁白结束后才结束视频,确保解说完整。它支持多种触发方式(如“创建带旁白的视频”、“录制A/B对比视频”、“团队演示视频”),并内置了多种故障处理机制(如Playwright无头shell缺失、ffmpeg缺少drawtext滤镜等)。用户需配合Bun、ffmpeg和Python 3在macOS Apple Silicon上使用,也可通过环境变量和参数适配其他平台。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sblattj/agent-chandlery/tree/main/skills/narrated-ab-video

在你喜欢的 AI 中提问

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

文档

B视频 是做什么的?

更多触发方式

PR的演练视频、制作演示录制、带旁白的演示、录制两个版本、讲解视频、无drawtext滤镜、Playwright的recordVideo、缺少无头shell

每个声明集对应一个MP4文件:标题卡片、A片段、B片段、证据卡片、裁决卡片,每段均有配音。

专为搭载Apple Silicon的macOS构建(say命令,Playwright缓存位于~/Library/Caches/ms-playwright,chrome-mac-arm64)。在其他平台,请设置CHROMIUM_EXE环境变量并使用--eleven参数指定语音。需要Bun、ffmpeg和Python 3。

执行步骤

S=${SKILL_DIR:-~/.claude/skills/narrated-ab-video}
$S/preflight.sh /tmp/vid                                  # 检查 chromium、playwright、ffmpeg、say 语音
bun $S/record.ts a.json raw/a-run                         # 每侧一个场景(复制 examples/scenario.json)
bun $S/record.ts b.json raw/b-run
bun $S/cards.ts cards.json cards                          # 生成标题/证据/裁决 PNG 以及 banner-A/B.png
python3 $S/build.py plan.json                             # [--voice Samantha] [--rate 182]
open -a "QuickTime Player" demo.mp4                       # 以暂停模式打开;切勿自行播放

示例文件位于 examples/ 目录:scenario.json(步骤包括:wait、select、click、clickIfPresent、type、send、waitStable、expand、fetchText、waitText、probeEnabled、reload;详见 record.ts 头部注释),cards.json,plan.json。计划文件中的路径相对于计划文件本身。已通过两个真实片段构成的4段、40秒构建进行了端到端验证。

如此构建的原因(痛点挖掘)

  • Playwright 固定的无头 shell 经常未下载。 record.ts 和 cards.ts 启动最新缓存中的完整 chromium-* 构建(或 $CHROMIUM_EXE)而非报错。
  • recordVideo 需要 Playwright 自带的 ffmpeg 构建版本。 缺少则无法生成 webm。preflight 从 browsers.json 读取修订号并运行 bunx playwright install ffmpeg。
  • Homebrew 安装的 ffmpeg 可能缺少 drawtext 滤镜。 角标由 cards.ts 生成为透明 PNG,在 build.py 中叠加。无需寻找字体或滤镜。
  • 模型回复需要10到60秒的静默时间。 send 标记“已发送”,waitStable 标记“已回复”。build.py 以 speed(默认10倍速)播放该段时间,其余部分以1倍速播放。
  • 旁白通常比视频片段长。 build.py 保持最后一帧(tpad stop_mode=clone)直到语音结束,因此回复画面在解说期间保持可见。
  • 动态输入(OTP码、先前轮次的ID): 在 type 步骤中使用 {{fn:NAME}},并从场景旁的 hooks.ts 中导出 NAME(page, state)。state.lastJson 保存匹配 captureJsonFrom 的最后一个POST JSON。
  • 选择器: 按钮通过角色和名称正则表达式匹配(例如 "Tools used"、"^Send$")。CSS 仅用于输入框和下拉框。在编写脚本前可先截图快速确认名称。
  • 拼接需要相同的编码参数。 每个片段均使用相同的编解码器、帧率和音频布局重新编码,然后通过 -c copy 合并。
  • 更好的语音: ELEVENLABS_API_KEY=... build.py plan.json --eleven <voice_id>(模型 eleven_multilingual_v2;片段按语音+文本哈希缓存,因此重复运行不消耗字符)。请将密钥保存在权限为 0600 的文件中,切勿写入计划文件,使用后删除。
  • 单侧演示(无A/B对比): 录制一个场景,为 cards.json 提供单个角标,并将同一片段切割为多个计划片段,每个片段对应一个声明,使用 spans 加速等待时间(例如5倍速)。构建方式相同,无 A 侧。
  • 用户可能仅粘贴 <voice_id> <key>。 这意味着使用 --eleven <voice_id> 重新构建。较慢的语音会延长视频时长(72秒的 say 版本变为92秒),因为 build.py 会保持最后一帧直到语音结束。
  • 拍摄前重新搭建已拆除的演示环境: 短期有效的认证(本地JWT、隧道URL、临时云资源)通常次日即失效。在录制前先通过一次API运行重新验证;如果出现“JWT token expired”的401错误,则拍摄的轮次将永远收不到结果。
  • 丢失原始片段: 从之前的输出MP4中裁剪该侧的录像(通过角标颜色采样找到其span),保存为 <dir>/a.webm(使用 -f mp4 和空的 marks.json),并使用一个明确的 span。由于角标已嵌入,请忽略 banner。
  • 音频: say -o 仅写入文件。未经用户明确同意,切勿播放视频或任何音频。以暂停模式打开并交给用户。
  • 先证明再拍摄。 先运行A/B对比并断言结果(通过API或日志)。视频展示的是已证明的结果,并非测试本身。
  • 卡片尺寸必须与片段尺寸一致。 build.py 不会进行缩放。若录制时使用 "viewport": [1440, 900],则 cards.json 中的 "size" 必须为 [1440, 900],否则拼接时会出现帧尺寸不一致。
  • 异步UI需要标记,而非固定等待。 waitText 在正则表达式匹配时标记(或通过 timeout:<mark> 标记),probeEnabled 配合 waitMs 轮询按钮并将 probes[] 记录在 marks.json 中,tryMs 在 type/send/click 上标记 skipped:<step> 而非中止,因此“保持禁用”的一侧仍能完成片段。
  • 探测与你点击相同的元素。 CSS 探测(button[aria-label=...])命中的按钮可能与角色名称 send 不同,导致读取禁用状态时发送已通过;请在 probeEnabled 中使用 "role"。
  • 开发者模式覆盖层(查询开发者工具、错误提示)会出现在片段中。 在首次等待后添加 {"clickIfPresent": "^Close .* devtools$"}。
  • 等待一个从未“稳定”的回复: 实时运行时长标记会每秒改变正文文本。在构建前检查 marks.json 中是否有 replied 标记。
  • 确认证据在可见文本中。 折叠的工具卡片可能不会展开(expand 无声地点击无效内容)。读取 marks.json 中的 body 以查找声明字符串。如果缺失,请更改提示或改在卡片上证明。
  • 在拍摄“基础版本失败”的声明前,先证明两者等价。 曾经有一次本地基础版本因某个标记(本地开启、远程关闭)而失败,而实际环境从未遇到该问题,但旁白却声称失败。请先匹配远程的标记,然后再拍摄。
  • 标题卡片:每侧测试的提交和标记。每个片段对应一个声明。以裁决卡片结束。

相关技能

  • narrated-screenshot:生成带注释的静态图片而非视频。
  • pr-ab-evidence:该技能拍摄的红色/绿色 A/B 对比方法。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能