Communitygithub.com

agentshot:截图与演示视频

在 Windows 和 macOS 上制作产品截图和演示视频 - 捕获 Web 应用 / Expo Web 应用 / 桌面窗口 / iOS 模拟器 / iPhone 文件,然后为其添加样式(背景、iPhone/浏览器/窗口边框、立体、放大镜、箭头、步骤、模糊、缩放、光标、裁剪),并渲染为 PNG 或 MP4 文件存入版本化库中。在用户要求为其应用提供截图、模型、帮助中心图片、更新日志图片、社交媒体帖子(X/Instagram)、演示/B 卷视频或屏幕录制时使用。

agentshot:截图与演示视频 是什么?

agentshot 是一个用于制作高质量产品截图和演示视频的工具,支持 Windows 和 macOS。它能够捕获各种来源的内容,包括 Web 应用、Expo Web 应用、桌面窗口(通过自动化的鼠标和键盘驱动)、iOS 模拟器,以及导入 iPhone 的截图或屏幕录制。用户可以通过编写 JSON 格式的“场景”来定义自动化的捕获流程,包括点击、输入、滚动和等待等步骤。捕获完成后,工具会提供详细的“检查”信息(如元素框、点击时间、视频中的静默段等),帮助用户规划裁剪和缩放。接着,通过编写 JSON 格式的“配方”(recipe),用户可以应用丰富的样式选项,如设备边框(iPhone、浏览器等)、背景、3D 倾斜、放大镜(loupe)、箭头标注、步骤编号、光标效果、模糊和裁剪,最终渲染为 PNG 图片或 MP4 视频。输出结果会存入一个版本化的库中,支持多次迭代和重新渲染。该工具特别适用于需要频繁更新应用截图和演示内容的开发者和产品团队。

兼容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/thread-of-ariadne/agentshot/tree/main/skill/agentshot

在你喜欢的 AI 中提问

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

文档

agentshot:截图与演示视频 是做什么的?

该工具位于 /path/to/agentshot。按如下方式运行:

node /path/to/agentshot/bin/agentshot.mjs <command> ...

下方agentshot指代该命令。每个命令都输出一行 JSON("ok": true|false)。长时间渲染的任务还会在 stderr 上输出进度。运行 agentshot help 可查看命令列表。

工作流程

  1. 首先阅读产品的规则:agentshot style <product> 会输出 style.json(默认外观)和 guidelines.md(用户偏好)。请遵循这些规则。如果产品是新建的,运行 agentshot style <product> --init。
  2. 捕获(选择其一):
    • Web 应用或 Expo 应用 → 编写包含 "url" 的场景 JSON 文件,运行 agentshot capture scenario.json。
    • Mac 上的 iOS 应用 → 编写包含 "simulator" 的场景(在 iOS 模拟器中的真实原生应用,参见 “iOS 模拟器”);快速静态截图 → agentshot sim snap --name <capture> --clean-status-bar。
    • 桌面程序 → 编写包含 "window" 的场景:你通过真实的鼠标/键盘驱动它,同时记录(参见 “桌面应用”)。仅需静态截图 → agentshot snap --window "<title>" --name <capture>。用户自行操作 → agentshot record start/stop。
    • 用户已有文件(iPhone 截图/屏幕录制) → agentshot import <file> --name <capture>。
  3. 检查:agentshot inspect <capture> 会列出截帧、元素框(屏幕坐标点)、点击时间、时长,以及对于视频,还会列出 moves(指针移动)、changes(页面切换:大的视觉跳变)、quiet(无任何变化:可裁剪或加速),以及场景的 timeline。根据这些数据规划裁剪和缩放,然后通过 agentshot frames <capture> --from a --to b 确认(一张带时间戳的联系表;请用读取工具查看其输出的 PNG)。在应用样式前,先用读取工具查看截帧的 PNG。
  4. 编写配方 JSON 文件并运行 agentshot render recipe.json --note "<what changed>"。
  5. 自行检查结果:读取 PNG;对于 MP4,使用 agentshot frames <product>/<asset>(整个视频)和 agentshot frames <product>/<asset> --from 3 --to 4 --every 0.033 --crop x,y,w,h(逐帧查看裁剪或点击附近区域)。修复并重新渲染(会添加新版本)。当用户希望自行手动调整或微调配方时,在后台运行 agentshot preview recipe.json:它会打开一个包含场景和滑块控件的本地页面,并在编辑配方(或产品的 style.json)时实时更新。它会输出一行包含 url 的 JSON,并持续提供服务。
  6. 报告输出路径(results[].output)。--copy-to <dir> 还会将其复制到用户的项目中。
  7. 学习:当用户纠正或表扬某些内容时,在产品的 guidelines.md 中追加带日期的注释(如果是默认外观,同时更新 style.json 的默认值)。下次使用时先读取它。

将场景和配方文件保存在用户的项目中(例如 docs/shots/),以便在 UI 更改后可以重新运行。

场景(捕获 Web 应用)

下面 JSON 示例中的注释仅为解释说明;实际文件必须是纯 JSON。

{
  "name": "ellie-today-drag",          // 捕获名称,唯一;以产品名称为前缀
  "url": "http://localhost:8081",       // 或者文件路径
  "device": "iphone",                   // iphone | iphone-max | ipad | desktop | laptop
  "safeArea": true,                     // Expo/RN Web:Chrome 会报告 iPhone 的安全区域 inset,应用布局方式
                                        // 如同在设备上一样("pad" = 为忽略 inset 的应用强制添加内边距)
  "css": "[class*='navigationMenuRoot'] { display: none }",  // 隐藏仅限 Web 的界面元素(Expo Router 的标签页在 Web 上会渲染为顶部菜单)
  "waitFor": "today-list",              // 在开始前等待此元素出现
  "track": { "row": "text=Plan a birthday" },  // 额外的命名元素框记录
  "steps": [
    { "shot": "main" },                                  // 全分辨率静态截图(用于截图)
    { "wait": 0.6 },
    { "tap": "add-button" },                             // 点击/轻触目标(会先移动到那里)
    { "type": "Buy milk", "into": "title-input" },
    { "press": "Enter" },
    { "drag": "task-birthday", "to": "slot-11am", "duration": 1.4 },
    { "scroll": 400, "duration": 0.8 },
    { "move": [200, 300], "duration": 0.6 },
    { "goto": "/settings" },
    { "waitFor": "settings-title" },
    { "shot": "after" }
  ]
}

目标:仅名称匹配 data-shot="..." 或 data-testid="..."(React Native 的 testID 在 Web 上会变成 data-testid,因此请为要指向的元素添加 testID),或任何 Playwright 选择器(text=Save、role=button[name="Save"]、#id、.class),或 CSS px 单位下的 [x, y]。所有具有 data-shot/data-testid 的元素及其边框都会被记录,同时 track 条目也会被记录。

时间控制:默认情况下("timing": "frame")页面时钟会被暂停,并以每帧(60 fps)的方式精确推进,每帧都渲染全分辨率截图,因此应用动画在任何分辨率下都很流畅;捕获时间会比场景实际时间长几倍。仅当应用在受控时钟下出错(某个步骤超时)时使用 "timing": "real"。agentshot capture 会报告点击时间(clicks),以便规划 cuts/zoom,以及控制台错误/警告(console)。开发者覆盖层(Expo LogBox toast、Next.js 指示器)会被隐藏;设置 "devOverlays": true 可保留它们。建议使用一个连续的 cuts 片段,而不是多个硬切割:片段之间的跳跃看起来会很生硬。

在无 testID 的应用中查找目标:使用 Playwright 打开页面,列出按钮和输入框(role、aria-label、文本),然后使用 text=...、role=button[name=/^My daughter/] 或 [aria-label='Your prayer'],并通过 track 命名你希望突出显示或放大查看的元素框。如果输入框被固定页脚遮挡,仍然可以正常输入(输入框会获得焦点)。

Expo:首先启动 Web 构建(npx expo start --web,通常地址为 http://localhost:8081)。仅限原生平台的模块可能在 Web 上无法工作;如果某个界面崩溃,请向用户索要 iPhone 截图/录制并 import。

桌面应用(包含 "window" 的场景)

agentshot windows 会列出窗口(标题、进程、尺寸)。通过标题匹配窗口,然后按进程名匹配,如果窗口最小化则恢复并前置。坐标是窗口像素:请先查看静态截图(agentshot snap --window "X" --name x-probe,读取 PNG),并在 track 中命名你使用的元素框。

{
  "name": "notes-tour",
  "window": "Notes",                              // 标题部分或进程名
  "track": { "nav-recent": [20, 200, 190, 40], "nav-search": [20, 96, 190, 40], "content": [232, 40, 1030, 650], "profile": [16, 718, 150, 62] },
  "cursor": [1000, 330],                          // 指针起始位置
  "steps": [
    { "shot": "home" },                           // 静态截图 = 此时记录的帧
    { "wait": 1 },
    { "click": "nav-recent", "duration": 0.9 },   // 滑移到那里(带缓动,轻微弧形),立即点击
    { "waitStill": 0.6, "region": "content" },    // 等待屏幕变化,然后等待稳定
    { "shot": "recent" },
    { "wheel": 4, "at": [760, 460] },             // 向下滚动 4 格(负值 = 向上)
    { "click": "nav-search" }, { "press": "ctrl+a" },
    { "type": "Weekly plan", "cps": 12 },         // 任意文本,包括非拉丁字符
    { "press": "Enter" },                         // 按键:enter esc tab space backspace delete arrows home end f1..f12, ctrl/alt/shift/win+x
    { "drag": [100, 300], "to": [400, 300], "duration": 1.2 },
    { "click": [640, 400], "button": "right" }, { "click": [640, 400], "double": true },
    { "note": "beat 2" }                          // 时间线中的标记
  ]
}
  • 结果中包含 timeline(每个步骤在视频中的开始/结束时间,at = 点击时刻)和 shots(从视频中截取的静态帧)。配方使用 track 名称作为目标(如对 "profile" 进行 "blur" 等)。

  • waitStill 首先等待(最长 changeTimeout,3 秒)直到区域与之前不同(change,平均像素差值,默认 6;"change": false 则仅等待稳定),然后等待指定秒数内无变化(threshold 0.6)。使用不包含动画部分(播放器、动态背景)的 region。

  • 到达后立即点击:光标在控件上停留约 0.5 秒会使 Windows 工具提示出现在视频中。

  • 对于保留旧文本的输入框:在 type 之前先 press ctrl+a。

  • 驱动程序在录制前启动(需要几秒钟)并移动真实光标:在此期间不要使用机器。桌面捕获为 1x 缩放,因此放大镜效果会显得模糊;建议使用 lift。

  • 可在录制的任意时间点获取静态帧:agentshot snap <capture> --at 12.4 --shot name。

  • 微小变化(如弹出窗口关闭)可能不足以使整个窗口的 change 阈值触发:请指定变化周围的 region。

  • 快捷键:mod 在 Windows 上是 Ctrl,在 macOS 上是 Cmd("press": "mod+a"),因此一个场景可以在两个系统上运行。

手动录制(用户执行操作;光标位置由渲染器记录和绘制):

agentshot record --name app-filter --window "Figma" --duration 12   # 录制 12 秒,然后停止
agentshot record start --name app-filter --window "Figma"           # 或开始 ...
agentshot record stop                                               # ... 并稍后停止

macOS

命令和场景与 Windows 相同;录制器 recorder/mac.swift 会在首次使用时编译(需要 Xcode Command Line Tools 和 macOS 14+)。首先运行 agentshot doctor:运行代理的应用(Terminal、iTerm、Claude、VS Code)需要在系统设置 > 隐私与安全性中启用屏幕录制和辅助功能权限(agentshot doctor --request 会打开权限提示;授权后重新启动该应用)。没有屏幕录制权限时,窗口标题仅显示应用名称,录制会失败;没有辅助功能权限时,驱动程序无法点击或输入。

  • 坐标(track、步骤、配方目标)是点;静态帧和视频使用显示器的像素缩放比例(Retina 上为 2,inspect 会显示 scale),因此 lift 和 zoom 效果保持清晰。
  • ScreenCaptureKit 录制的是窗口本身:窗口可以部分被遮挡,但不能最小化。
  • node scripts/selftest-mac.mjs 会在 TextEdit(以及已启动的模拟器)上检查所有功能,并打印失败的模块。同步检查:agentshot record ... --show-cursor 会烧录真实光标;将其与记录的指针位置进行对比(像其他录制一样使用 agentshot frames 和 inspect)。

iOS 模拟器 (macOS)

使用原生应用而非其 Web 版本:真实的字体、原生模块、iOS 动画。启动一个模拟器(open -a Simulator),在其中运行应用(npx expo run:ios 或开发构建),然后:

agentshot sim devices                                       # 已启动的模拟器
agentshot sim snap --name app-home --clean-status-bar       # 无损静态截图,显示 9:41 / 满电量
agentshot sim record start --name app-flow                  # 其他人操作 ...
agentshot sim record stop

场景使用 idb 驱动(brew install facebook/fb/idb-companion,pipx install fb-idb);坐标是设备点(读取 sim snap 的图片后将其像素值除以 scale):

{
  "name": "app-onboarding",
  "simulator": "booted",                        // 或 UDID 或设备名称的一部分
  "statusBar": "clean",                         // 捕获期间显示 9:41,捕获后清除
  "appearance": "light",                        // 或 "dark"
  "openUrl": "exp://127.0.0.1:8081/--/today",   // 录制前打开的深度链接(或 "launch": "<bundle id>")
  "track": { "add": [330, 760, 48, 48], "title": [24, 120, 340, 44] },
  "steps": [
    { "shot": "today" },
    { "tap": "add" },
    { "waitStill": 0.5 },
    { "type": "Buy milk" },                      // 输入到当前焦点所在的输入框
    { "press": "enter" },                        // enter esc backspace tab space arrows home lock
    { "swipe": [200, 600], "to": [200, 250], "duration": 0.4 },
    { "openUrl": "exp://127.0.0.1:8081/--/settings" },
    { "waitStill": 0.6 },
    { "shot": "settings" }
  ]
}

静态帧是模拟器的无损截图;轻触和滑动操作会变成触摸指针和点击,因此配方中使用 "pointer": "touch" 和 "device": "iphone-black",与浏览器捕获类似。如果没有 idb,则只有 wait/waitStill/agentshot/openUrl/launch 步骤可以工作。

配方(样式与渲染)

{
  "name": "today-drag",                 // 库中的资产名称
  "product": "ellie",                   // 库文件夹;应用 style.json 的默认值
  "capture": "ellie-today-drag",
  "shot": "main",                       // 设置为 PNG 静态截图的截帧名称;省略则生成 MP4 视频
  "size": "16:9",                       // 16:9 16:10 4:3 3:2 1:1 4:5 9:16, 或宽/高
  "background": "lavender",             // lavender peach sage sky rose mint neutral midnight ink white,
                                        // 任意 CSS 颜色/渐变,或 public/ 目录下的图片(backgrounds/x.jpg)
  "backgroundBlur": 0.02,               // 对于照片背景,为短边占比
  "device": "iphone-black",             // iphone-black iphone-natural iphone-white browser window none
  "url": "app.ellie.so/today",          // 浏览器地址栏文本;"title":窗口标题(用于 "window")
  "padding": 0.08, "tilt": 12,          // 设备外边距;3D 倾斜角度(度)
  "position": [0.69, 0.5],              // 设备在画布上的中心位置,为标题等留出空间
  "accent": "#6d5ce8",                  // 步骤编号、轮廓、标签、点击涟漪的颜色
  "font": "Gilda Display", "labelFont": "Inter",  // 标题 / 放大标签字体:Inter Manrope Poppins Nunito Fraunces Lora
                                        // "Playfair Display" "DM Serif Display" "Gilda Display" "Cormorant Garamond" Caveat
  "lift":  { "target": "task-row", "label": "Drag it onto your day", "start": 3.9, "pad": 10, "dim": 0.1 },
  "loupe": { "target": "label-chip", "anchor": [0.2, 0.5], "zoom": 2.3, "size": 0.12, "offset": [-0.15, 0.12] },
  "annotations": [
    { "t

相关技能