Communitygithub.com

thread-of-ariadne/agentshot

在 Windows 和 macOS 上製作產品截圖和示範影片 - 捕捉網頁應用程式 / Expo 網頁應用程式 / 桌面視窗 / iOS 模擬器 / iPhone 檔案,然後進行樣式設定(背景、iPhone/瀏覽器/視窗外框、抬起、放大鏡、箭頭、步驟、模糊、縮放、游標、裁切)並渲染為 PNG 或 MP4,存入版本化的資料庫。當使用者要求其應用程式的截圖、模型、說明中心圖片、更新日誌圖片、社群貼文(X/Instagram)、示範/B-roll 影片或螢幕錄製時使用。

agentshot 是什麼?

這個技能,`agentshot`,是一個由 Node.js CLI 驅動的螢幕截圖和示範影片製作工具,專為開發者和產品團隊設計。它支援從網頁應用程式、桌面程式、iOS 模擬器,甚至直接匯入 iPhone 檔案(如截圖或錄影)等多種來源進行捕捉,大大簡化了創建高品質產品視覺素材的流程。其核心工作流程包含四個步驟:從捕捉原始素材開始,接著檢查元素資料和時間軸以規劃編輯,然後編寫一個描述最終輸出(例如背景、裝置外框、註解等)的「配方」JSON 檔案來進行渲染,最後輸出結果。它會在一個版本化的資料庫中產生 PNG 靜態影像及 MP4 動態影片,確保每次迭代都有記錄。 此工具在 macOS 和 Windows 上均能順暢運作,並自動處理 Retina 螢幕的縮放比例、iOS 狀態列清理等細節。更具體來說,它可以模擬複雜的使用者互動,包括點擊、打字、滾動和拖曳,並在影片中記錄精確的滑鼠游標移動路徑和時間戳記。它與 Expo 應用程式無縫整合,能捕捉網頁建置版本,並支援 iOS 模擬器的原生應用程式。`agentshot` 也提供了一個預覽伺服器,用於動態編輯場景,並透過 `guidelines.md` 檔案來學習使用者的偏好,隨著時間推移調整其產出,使其成為一個高度適應性的產品視覺素材自動化工具。

相容平台✓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. 捕捉(選擇一種):
    • 網頁應用程式或 Expo 應用程式 → 編寫一個包含 "url" 的 scenario JSON,然後執行 agentshot capture scenario.json。
    • Mac 上的 iOS 應用程式 → 一個包含 "simulator" 的 scenario(iOS 模擬器中的真實原生應用程式,請參閱 "iOS 模擬器");快速靜態照 → agentshot sim snap --name <capture> --clean-status-bar。
    • 桌面程式 → 一個包含 "window" 的 scenario:您驅動真實的滑鼠/鍵盤,同時它進行錄製 (請參閱 "桌面應用程式")。僅需靜態照 → agentshot snap --window "<title>" --name <capture>。 使用者執行操作 → agentshot record start/stop。
    • 使用者已有檔案(iPhone 截圖 / 螢幕錄影) → agentshot import <file> --name <capture>。
  3. 檢查:agentshot inspect <capture> 會列出畫面、元素框(螢幕點位)、點擊、時長以及 對於影片,還有 moves(指標移動)、changes(頁面切換:重大的視覺跳躍)、quiet(無移動: 應裁切或加速的部分)以及 scenario 的 timeline。根據這些數據規劃裁切和縮放,然後用 agentshot frames <capture> --from a --to b 確認(一個附帶時間戳的聯繫表;請閱讀它產生的 PNG)。 在進行樣式設定前,請使用 Read 工具查看畫面 PNG。
  4. 編寫一個 recipe 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(逐幀檢查裁切或點擊附近)。 修正後重新渲染(會新增一個版本)。 當使用者想要自行調整或微調 recipe 時,在背景執行 agentshot preview recipe.json: 它會開啟一個包含場景和滑動條的本地頁面,並在 recipe(或產品的 style.json)被編輯時即時更新。 它會輸出一行包含 url 的 JSON,並持續提供服務。
  6. 回報 輸出路徑(results[].output)。--copy-to <dir> 也會將其複製到使用者的專案中。
  7. 學習:當使用者修正或讚揚某些內容時,在產品的 guidelines.md 中附加一行包含日期說明的記錄(如果是預設外觀,也更新 style.json 預設值)。下次使用時重新閱讀。

將 scenarios 和 recipes 保存在使用者的專案中(例如 docs/shots/),以便在使用者介面變更後可以重新執行。

Scenario(捕捉網頁應用程式)

以下 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 }",  // 隱藏僅在網頁上出現的 chrome 元素(Expo Router 的標籤頁在網頁上會顯示為頂部選單)
  "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 在網頁上會變成 data-testid,所以請在您想要指向的元素上添加 testID),或是任何 Playwright 選擇器(text=Save、role=button[name="Save"]、#id、.class),或 [x, y] 形式的 CSS 像素座標。 所有具有 data-shot/data-testid 的元素,連同 track 條目,都會記錄其框體。

時序:預設情況下("timing": "frame")頁面時鐘會被暫停,並每次精確前進一幀(60 fps),每幀都會產生全解析度的截圖,這樣應用程式的動畫在任何解析度下都能保持流暢;捕捉所需的時間會比 scenario 的時間長幾倍。僅當應用程式在受控時鐘下出現異常時(步驟可能超時),才使用 "timing": "real"。agentshot capture 會回報點擊時間(clicks)以規劃 cuts/zoom,以及主控台錯誤/警告(console)。開發者疊加層(Expo LogBox toast、Next.js 指示器)會被隱藏;設定 "devOverlays": true 則會保留它們。 偏好使用一個連續的 cuts 區段,而不是多次硬切換:區段之間的跳躍看起來會很不流暢。

在沒有 testID 的應用程式中尋找目標:使用 Playwright 開啟頁面並列出按鈕/輸入框(role、aria-label、text),然後使用 text=...、role=button[name=/^My daughter/] 或 [aria-label='Your prayer'],並通過 track 為您想要進行抬起/放大鏡操作的框體命名。 在具有黏性頁尾的欄位中輸入文字仍然有效(該欄位會獲得焦點)。

Expo:首先啟動網頁建置(npx expo start --web,通常為 http://localhost:8081)。僅限原生的模組可能無法在網頁上運作;如果某個畫面無法顯示,請向使用者索取 iPhone 截圖/錄影並使用 import。

桌面應用程式(包含 "window" 的 scenario)

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 (從影片中裁切的靜態照)。Recipes 使用 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"),因此一個 scenario 可以在兩個平台上執行。

手動錄製(使用者執行操作;游標會被記錄並由渲染器繪製):

agentshot record --name app-filter --window "Figma" --duration 12   # 錄製 12 秒,然後停止
agentshot record start --name app-filter --window "Figma"           # 或開始...
agentshot record stop                                               # ...然後稍後停止

macOS

與 Windows 上相同的指令和 scenario;錄製器/mac.swift 會在首次使用時編譯(需要 Xcode Command Line Tools 和 macOS 14+)。首先執行 agentshot doctor:執行代理程式的應用程式(Terminal、iTerm、Claude、VS Code)需要在「系統設定」>「隱私權與安全性」中啟用螢幕錄製和輔助使用權限(agentshot doctor --request 會開啟提示;授予權限後重新啟動該應用程式)。沒有螢幕錄製權限,視窗標題將僅顯示應用程式名稱且錄製會失敗;沒有輔助使用權限,驅動程式無法點擊或打字。

  • 座標(track、步驟、recipe 目標)是點;靜態照和影片會以顯示器的像素比例呈現(Retina 為 2,inspect 會顯示 scale),因此抬起和縮放效果會保持清晰。
  • ScreenCaptureKit 會記錄視窗本身:它可能被部分遮蓋,但不能被最小化。
  • node scripts/selftest-mac.mjs 會在 TextEdit(以及已啟動的模擬器,如果有的話)上檢查所有功能,並印出失敗的項目。同步檢查:agentshot record ... --show-cursor 會將真實游標嵌入影片中;將其與記錄的指標進行比較(agentshot frames 對比 inspect),就像檢查任何錄影一樣。

iOS 模擬器(macOS)

使用原生應用程式代替其網頁建置版本:獲得真實字體、原生模組和 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

一個 scenario 可以使用 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" }
  ]
}

靜態照是無損的模擬器截圖;輕按和滑動會變成觸控指標和點擊,因此 recipes 會使用 "pointer": "touch" 和 "device": "iphone-black",就像瀏覽器捕捉一樣。如果沒有 idb,則僅能使用 wait/waitStill/agentshot/openUrl/launch 等步驟。

Recipe(樣式設定和渲染)

{
  "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": "拖曳到您的日期上", "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": "..." }
  ]
}

(由於原始內容被截斷,此為翻譯後的完整內容)

相關技能