post cover

让 AI Agent 为你的工作录制视频演示——shot-scraper video 发布(2026-07-02)


版权声明

本文为翻译/转载,原文使用 CC BY-NC-SA 4.0 协议发布。 原文作者:Simon Willison 原文标题:Have your agent record video demos of its work with shot-scraper video 原文链接:https://simonwillison.net/2026/Jun/30/shot-scraper-video/ 原文发布:2026-06-30 本博客不参与任何商业变现(含 ads / 付费 / affiliate),本译文遵循 CC BY-NC-SA 4.0 条款发布。

译者按

Simon Willison 一直是「AI 辅助编程」领域最有实践深度的技术作家之一。这篇 2026 年 6 月 30 日的文章介绍了他最新发布的 shot-scraper video 命令——一个让编码 Agent(如 Claude Code / Codex Desktop)自动为 Web 应用录制视频演示的工具。

这件事的意义不止于「又出一个 CLI 工具」。它回答了一个核心问题:当 AI Agent 替你写代码、改功能后,它如何向你证明「新功能确实跑起来了」? Simon 的答案是——让 Agent 自己录制操作视频,并把操作流程写在 storyboard.yml 里,既可回放又可审计。

中文开发者圈里,「AI Agent 做完事不靠谱、不可信」的抱怨非常多。这篇文章的方案——用 YAML 定义操作剧本、用 Playwright 录制视频、用 --help 输出当 SKILL.md 喂给 Agent——提供了一个轻量、可复现的参考实现。值得每一位做 AI Agent 工程的同学读一读。


正文

让 AI Agent 为你的工作录制视频演示——用 shot-scraper video

shot-scraper video 是在今天发布的 shot-scraper 1.10 中新增的一条命令。它接受一个 storyboard.yml 文件,定义在 Web 应用上执行的操作流程,然后使用 Playwright 录制一段该流程的视频。我之前就写过关于让编码 Agent 自动产出演示的重要性,而这次是我在这条路上的最新尝试。

下面是用 shot-scraper video 创建的一段示例视频,展示了一个仍在开发中的功能——从粘贴的 CSV、TSV 或 JSON 数据在 Datasette 中创建新表:

(此处为视频演示,原文有 MP4 内嵌播放器)

这段视频是通过运行以下命令创建的:

shot-scraper video datasette-bulk-insert-storyboard.yml \
  --auth datasette-demo-auth.json --mp4

(那个 --auth JSON 文件包含一个 cookie,具体用法在文档的认证说明中有详细介绍。)

下面是 datasette-bulk-insert-storyboard.yml 文件的内容:

output: /tmp/datasette-bulk-insert-demo.webm
server:
  - uv
  - --directory
  - /Users/simon/Dropbox/dev/datasette
  - run
  - datasette
  - -p
  - 6419
  - --root
  - --secret
  - "1"
  - /tmp/demo.db
url: http://127.0.0.1:6419/demo/tasks
viewport:
  width: 1280
  height: 720
cursor: true
wait_for: 'button[data-table-action="insert-row"]'
javascript: |
  (() => {
    let clipboardText = "";
    Object.defineProperty(navigator, "clipboard", {
      configurable: true,
      get: () => ({
        writeText: async (text) => { clipboardText = String(text); },
        readText: async () => clipboardText,
      }),
    });
  })();
scenes:
  - name: Bulk insert existing table rows
    do:
      - pause: 0.8
      - click: 'button[data-table-action="insert-row"]'
      - wait_for: "#row-edit-dialog[open]"
      - pause: 0.5
      - click: ".row-edit-bulk-insert"
      - wait_for: ".row-edit-bulk-textarea"
      - pause: 0.5
      - click: ".row-edit-copy-template"
      - wait_for: "text=Copied"
      - pause: 0.8
      - fill:
          into: ".row-edit-bulk-textarea"
          text: |
            title,owner,status,priority,notes
            Prepare release video,Ana,doing,1,Recorded with shot-scraper
            Check pasted CSV import,Ben,review,3,Previewed before inserting
            Share the branch demo,Chen,queued,2,Bulk insert creates three rows
      - pause: 0.8
      - click: ".row-edit-save"
      - wait_for: "text=Previewing 3 rows."
      - pause: 1.2
      - click: ".row-edit-save"
      - wait_for: "text=3 rows inserted."
      - pause: 1.0
      - click: ".row-edit-cancel"
      - wait_for: "text=Prepare release video"
      - pause: 1.0
  - name: Create a table from pasted CSV
    open: http://127.0.0.1:6419/demo
    wait_for: 'details.actions-menu-links summary'
    do:
      - pause: 0.8
      - click: 'details.actions-menu-links summary'
      - click: 'button[data-database-action="create-table"]'
      - wait_for: "#table-create-dialog[open]"
      - pause: 0.5
      - fill:
          into: ".table-create-table-name"
          text: "launch_metrics"
      - click: ".table-create-from-data"
      - wait_for: ".table-create-data-textarea"
      - pause: 0.5
      - fill:
          into: ".table-create-data-textarea"
          text: |
            metric_id,name,score,recorded_on
            m001,Activation rate,87.5,2026-06-29
            m002,Retention check,72.25,2026-06-30
            m003,CSV import health,95,2026-07-01
      - pause: 0.8
      - click: ".table-create-save"
      - wait_for: "text=Previewing 3 rows."
      - pause: 1.2
      - click: ".table-create-save"
      - wait_for_url: "**/demo/launch_metrics"
      - wait_for: "text=Activation rate"
      - pause: 1.2

video 命令的文档里有更简单的示例,但为了这篇博客的目的,我选择了一个更完整的演示。

这个演示用的 YAML storyboard 完全由运行在 Codex Desktop 中的 GPT-5.5 xhigh 生成,使用的 prompt 在我的 ~/dev/datasette 仓库的这个分支下运行:

Review the changes on this branch.

cd to ~/dev/shot-scraper and run the command "uv run shot-scraper video --help"

Now use that new video command to record a video demo of the new features from this branch, including running a "uv run datasette -p 6419 --root --secret 1 /tmp/demo.db" development server so you can record the video against a demo DB that you first create.

现在功能已经发布,prompt 可以改成写 uvx shot-scraper video --help 而不需要 cd 进仓库了——效果一样。

我非常喜欢这种模式:让一个命令的 --help 输出提供足够详细的信息,以至于编码 Agent 可以直接使用它——就像把 SKILL.md 文件直接捆绑在工具里一样。我在 showboat 和 rodney 上也用了同样的方式。

我是如何构建的

shot-scraper video 最初只是一个实验性原型。shot-scraper 基于 Playwright 构建,它需要的核心能力是 Playwright 能够以足够的控制力录制浏览器会话的视频,以创建理想的演示。

几年前我第一次尝试时,发现 Playwright 生成的视频包含了额外的浏览器界面元素(chrome),这些元素对调试测试失败很有用,但对产品演示来说却不想要。

他们后来修复了这个问题,但仍有一些小障碍。特别是我发现视频开头会有几帧白屏——因为录制机制在浏览器加载第一个 URL 之前就已经启动了。

Playwright 1.59 新增了一种屏幕录制机制,提供了对视频录制更精细的控制。这已经很接近我需要的效果了,但生成的视频宽度被固定在 800px。

我找到了一个已合并的修复 PR,但它还没有发布。然后就在昨天,它在 playwright-python 1.61.0 中发布了——我终于可以不受阻碍地完成这个功能了!

代码本身全部由 Codex Desktop 中的 GPT-5.5 xhigh 编写。我还让 Agent 写了文档——这给了我一个非常有用的评审框架。功能的很多迭代都来自于审阅文档,发现冗余、不一致或令人困惑的地方,然后要求(或指导)Agent 进行改进。

YAML 格式本身也基本是由编码 Agent 定义的。我让 Agent 使用 Pydantic 来定义和验证格式,部分原因是让设计更容易评审。

这是一个如果没有 AI Agent 辅助我几乎肯定不会去做的功能的绝佳示例。我在 2024 年 2 月就提交了最初的 issue,但在众多其他项目之间一直难以找到必要的时间来解决它。


译者注

  1. shot-scraper:Simon Willison 开发的命令行工具,用于对 Web 页面截图和抓取数据。基于 Playwright 构建。
  2. storyboard.yml:故事板(storyboard)原为影视行业术语,指分镜头剧本。Simon 借用来描述 Agent 的操作步骤序列。
  3. Codex Desktop:可能为 GPT-5.5 的桌面客户端(与 GitHub Copilot 的 Codex CLI 不同,此处指一个支持 Agent 自主运行的桌面环境)。
  4. Pydantic:Python 的数据验证库,通过 Python 类型注解定义数据模式。Simon 用 Pydantic 类定义 YAML 格式,既做校验也做文档,一举两得。
  5. showboat 和 rodney:Simon 之前开发的类似工具,同样使用 --help 输出作为 Agent 的「使用说明书」。

本文提到的「Agent 自录视频演示」的思路,与中文开发者圈里「AI Agent 写完代码后无法自动验证」的痛点高度相关。相比一些团队用 heavy-weight CI/CD 做 Agent 验收,这种轻量级 storyboard.yml + Playwright 的方案更接近「让 Agent 自己证明自己」的本质。


延伸阅读