watch

watch

熱門

觀看影片(網址或本機路徑)。使用 yt-dlp 下載,用 ffmpeg 提取自動縮放影格,從字幕(或 Whisper API 備援)取得逐字稿,然後將結果交給 Claude,讓它能回答關於影片內容的問題。

9177星標
983分支
更新於 2026/7/1
SKILL.md
唯讀
名稱
watch
描述

觀看影片(網址或本機路徑)。使用 yt-dlp 下載,用 ffmpeg 提取自動縮放影格,從字幕(或 Whisper API 備援)取得逐字稿,然後將結果交給 Claude,讓它能回答關於影片內容的問題。

版本
0.2.0

/watch

你沒有影片輸入功能;這個技能提供給你。Python 腳本會先取得字幕,選擇性下載影片,提取 JPEG 影格(場景感知,或在 efficient 詳細度下使用快速關鍵影格),取得帶時間戳的逐字稿(優先使用原生字幕,再以 Whisper API 備援),然後輸出影格路徑。接著你用 Read 讀取每個影格路徑來查看圖片,並結合逐字稿回答使用者。

解析 SKILL_DIR(在任何指令前執行)

以下每個 python3 ... 指令都會執行 SKILL_DIR/scripts/ 下的腳本。將 SKILL_DIR 設為包含你剛才讀取的這個 SKILL.md 的目錄的絕對路徑 — 你的 harness 會在 Read 結果中告訴你那個路徑。腳本永遠是這個檔案 (SKILL_DIR/scripts/watch.py) 的直接同層檔案,適用於任何安裝佈局:

Read ~/.claude/plugins/cache/claude-video/watch/<ver>/skills/watch/SKILL.md → SKILL_DIR=…/skills/watch
Read ~/.codex/skills/watch/SKILL.md                                          → SKILL_DIR=~/.codex/skills/watch
Read ~/.agents/skills/watch/SKILL.md                                         → SKILL_DIR=~/.agents/skills/watch

在每個指令中將 ${SKILL_DIR} 替換為該實際路徑。這適用於所有 harness(Claude Code、Codex、Cursor、Gemini CLI 等),無需依賴任何 harness 特定的環境變數。在執行開始時檢查一次:

SKILL_DIR="<你讀取的 SKILL.md 所在目錄的絕對路徑>"
if [ ! -f "$SKILL_DIR/scripts/watch.py" ]; then
  echo "錯誤:在 SKILL_DIR=$SKILL_DIR 下找不到 scripts/watch.py" >&2
  echo "請重新檢查你讀取的 SKILL.md 目錄,並將其設為 SKILL_DIR。" >&2
  exit 1
fi

步驟 0 — 設定預檢(每次 /watch 呼叫時執行,成功時靜默)

Python 直譯器: 本技能中的所有 python3 ... 指令都是為 macOS/Linux 設計的。在 Windows 上,請改用 python — Windows 上的 python3 指令是 Microsoft Store 的存根,無法執行腳本。

在會話中第一次呼叫 /watch 時,使用結構化預檢來偵測首次執行設定:

python3 "${SKILL_DIR}/scripts/setup.py" --json

根據兩個欄位進行分支:

  • can_proceed: truefirst_run: false → 設定已完成(使用者可能刻意跳過 Whisper 金鑰 — 這是允許的)。直接進入步驟 1,無需評論。
  • first_run: true → 真正的首次設定。依序執行以下操作:
    1. 如果 missing_binaries 不為空,先執行安裝程式(在 macOS 上會自動安裝,在其他系統上會印出指令 — 見下文)並確認二進位檔已就位。不要跳過此步驟直接跳到偏好設定。
    2. 如有需要再次執行安裝程式,以便它建立 ~/.config/watch/.env(它只在檔案不存在時寫入範本,所以讓它先建立檔案,然後你再寫入任何值)。
    3. 鼓勵使用者提供 Whisper API 金鑰並詢問觀看偏好問題,然後將選取的值寫入 ~/.config/watch/.env,並設定 SETUP_COMPLETE=true
  • can_proceed: falsefirst_run: false → 設定之前已完成,但環境退化了(例如作業系統變更後 missing_binaries)。執行安裝程式修復,然後繼續。不要重新詢問偏好。

缺少 Whisper 金鑰是鼓勵修復,而非必要:在真正的首次執行時,即使二進位檔已存在,status 也會顯示 needs_key — 這是提示你鼓勵提供金鑰,而非阻擋。

在同一個會話中後續呼叫 /watch 時,使用靜默檢查:

python3 "${SKILL_DIR}/scripts/setup.py" --check

這是一個小於 100ms 的查詢。退出碼 0 表示 /watch 可以執行 — 這包括已完成設定但沒有 Whisper 金鑰的使用者(無金鑰是允許的)。退出碼 0 時腳本不輸出任何內容 — 直接進入步驟 1,無需評論。不要向使用者宣告「設定完成」 — 他們不需要每次操作都看到狀態訊息。步驟 0 唯一可接受的使用者可見輸出是當需要修復時。

如果退出碼非零,請參考下表:

退出碼 意義 動作
2 缺少二進位檔(ffmpeg / ffprobe / yt-dlp 執行安裝程式
3 真正的首次執行,沒有 Whisper API 金鑰 執行安裝程式以建立 .env,然後鼓勵提供金鑰(使用者可以拒絕 — 使用 --no-whisper 繼續)
4 兩者都缺少 執行安裝程式,然後鼓勵提供金鑰

退出碼 3 只會在使用者完成設定前觸發。一旦寫入 SETUP_COMPLETE=true,無金鑰的安裝會回傳退出碼 0,且不會再被提醒。

安裝程式是冪等的 — 可以安全地重新執行:

python3 "${SKILL_DIR}/scripts/setup.py"

在 macOS 上(使用 Homebrew),它會自動安裝 ffmpegyt-dlp。在 Linux/Windows 上,它會印出確切的安裝指令讓使用者執行。它會建立 ~/.config/watch/.env,包含註解掉的佔位符和預設觀看設定,權限為 0600

如果安裝後仍然缺少 API 金鑰: 使用 AskUserQuestion 詢問使用者是否有 Groq API 金鑰(較推薦 — 更便宜、更快)或 OpenAI 金鑰。然後將其寫入 ~/.config/watch/.env — 設定對應的 GROQ_API_KEY=...OPENAI_API_KEY=... 行。如果他們不想設定 Whisper,使用 --no-whisper 繼續,並告知他們沒有原生字幕的影片將只回傳影格。

首次執行觀看偏好: 在安裝程式建立 ~/.config/watch/.env 後,使用 AskUserQuestion 詢問一個問題:

  • 預設詳細度(單一選項)。以以下順序呈現為 AskUserQuestion 選項 — 從最輕到最重 — 並將 (recommended) 保留在 balanced 上,即使它不是第一個(不要重新排序將推薦選項放在第一個):
    • transcript — 完全沒有影格,只有逐字稿(當有字幕時跳過影片下載)。
    • efficient — 快速關鍵影格(上限 50)。
    • balanced(推薦)— 場景感知影格(上限 100,預設)。
    • token-burner — 場景感知,無上限(最高精確度;高 token 成本)。

將答案直接寫入 ~/.config/watch/.env,將裸鍵設定在自己的行上 — 不要有行內註解(值後面的 # note 可能會破壞解析):

WATCH_DETAIL=balanced

使用使用者選取的值。如果他們跳過問題,保留推薦的預設值。處理完相依性、API 金鑰選擇和此偏好後,在同一個檔案中寫入或更新 SETUP_COMPLETE=true。當 SETUP_COMPLETE=true 時,不要再問這個偏好問題。

結構化模式(可選): python3 "${SKILL_DIR}/scripts/setup.py" --json 輸出 {status, can_proceed, first_run, setup_complete, missing_binaries, whisper_backend, has_api_key, config_file, watch_detail, platform},其中 statusready | needs_install | needs_key | needs_install_and_key 之一。status 描述理想狀態(金鑰是被鼓勵的,所以無金鑰的首次執行會顯示 needs_key);can_proceed 是操作閘門(二進位檔存在且金鑰已設定,或設定已完成)。根據 can_proceed/first_run 決定是否執行;使用 status 決定要鼓勵什麼。

在同一個會話中,後續的 /watch 呼叫可以跳過步驟 0 — 一旦 --check 回傳 0,環境在兩次操作之間不會改變。

何時使用

  • 使用者貼上影片網址(YouTube、Vimeo、X、TikTok、Twitch 剪輯、大多數 yt-dlp 支援的網站)並詢問相關問題。
  • 使用者指向本機影片檔案(.mp4.mov.mkv.webm 等)並詢問相關問題。
  • 使用者輸入 /watch <url-or-path> [question]

建議限制

  • 最佳準確度:10 分鐘以下的影片。 影格覆蓋率與時長成反比。
  • 通用速率上限:2 fps。 腳本取樣速度永遠不超過 2 fps,即使預算或 --fps 暗示更多。
  • 影格上限由詳細度模式設定~/.config/watch/.env 中的 WATCH_DETAIL,或 --detail),而非單一全域上限:
    • transcript → 無影格
    • efficient → 最多 50(關鍵影格)
    • balanced(預設)→ 最多 100(場景感知)
    • token-burner無上限(場景感知;超過 250 影格時會印出軟性警告)
    • --max-frames N 會覆蓋模式原本使用的任何上限。
  • 全片影格預算按時長計算。 Token 成本隨影格數量增加,因此腳本會根據時長設定預算。此預算設定 fps 和均勻取樣備援;場景感知選取最多可達上述詳細度上限,取較低者:
    • ≤30 秒 → 約 12-30 影格
    • 30 秒-1 分鐘 → 約 40 影格
    • 1-3 分鐘 → 約 60 影格
    • 3-10 分鐘 → 約 80 影格
    • >10 分鐘 → 最多到詳細度上限,稀疏間隔(會印出警告)
  • 如果使用者給你一個長影片,考慮詢問他們是否想要特定段落,再燃燒 token 進行稀疏掃描。

如何呼叫

步驟 1 — 解析使用者輸入。 將影片來源(網址或路徑)與使用者提出的任何問題分開。範例:/watch https://youtu.be/abc what language is this in? → 來源 = https://youtu.be/abc,問題 = what language is this in?

步驟 2 — 執行觀看腳本。 直接傳入來源。除了正常的引號外,不需要自己進行 shell 跳脫:

python3 "${SKILL_DIR}/scripts/watch.py" "<source>"

可選旗標:

  • --detail transcript|efficient|balanced|token-burner — 精確度/速度調節。transcript = 無影格(只有逐字稿,當有字幕時跳過影片下載);efficient = 快速關鍵影格(上限 50);balanced = 場景感知影格(上限 100);token-burner = 場景感知,無上限。
  • --start T / --end T — 聚焦於某個段落。接受 SSMM:SSHH:MM:SS。當設定任一項時,fps 會自動調整得更密集(見下方「聚焦於段落」)。
  • --timestamps T1,T2,… — 在這些絕對時間戳(SSMM:SSHH:MM:SS)各抓取一個影格。在讀取逐字稿後使用此選項,以捕捉講者標記的指示性時刻(「看這裡」、「如你所見」、「注意這個」),這些可能被純視覺選取錯過。見下方「逐字稿提示影格」。
  • --max-frames N — 覆蓋預設上限以獲得更緊的 token 預算(例如 --max-frames 40
  • --resolution W — 變更影格寬度(像素,預設 512;僅在使用者需要閱讀螢幕文字時才提高到 1024)
  • --fps F — 覆蓋自動 fps(上限為 2 fps)
  • --out-dir DIR — 將工作檔案放在特定目錄(預設:自動產生的暫存目錄)
  • --whisper groq|openai — 強制使用特定的 Whisper 後端(預設:如果兩個金鑰都存在,優先使用 Groq)
  • --no-whisper — 完全停用 Whisper 備援(如果沒有字幕,則只有影格)
  • --no-dedup — 保留近似重複的影格。預設情況下,影格差異檢查會丟棄與前一個保留影格視覺上幾乎相同的影格(靜態投影片、靜態螢幕錄製、暫停的影片),以便影格預算用於不同的內容;報告的 Frames 行會註明丟棄了多少。僅在使用者需要每個取樣影格時才傳遞此選項(例如判斷細微的影格間運動)。

聚焦於段落(較高影格率)

當使用者詢問特定時刻時 — 「2 分鐘處發生了什麼?」、「聚焦 0:45 到 1:00」、「前 10 秒」 — 傳遞 --start 和/或 --end。腳本會切換到聚焦模式預算,這比全片預算更密集(仍上限 2 fps,且仍受詳細度模式上限約束 — 以下計數假設預設 balanced 上限 100;efficient 上限為 50):

  • ≤5 秒 → 2 fps(最多 10 影格)
  • 5-15 秒 → 2 fps(最多 30 影格)
  • 15-30 秒 → 約 2 fps(最多 60 影格)
  • 30-60 秒 → 約 1.3 fps(最多 80 影格)
  • 60-180 秒 → 約 0.6 fps(100 影格,已達上限)

聚焦模式適用於:

  • 使用者明確指定的任何時刻/範圍(「大約 2:30」、「開頭」、「最後 30 秒」)。
  • 任何長於約 10 分鐘的影片,且使用者的問題是關於特定部分 — 對相關段落執行聚焦模式遠比對整個影片進行稀疏掃描有用得多。
  • 在全片掃描後,某個區域細節不足時重新執行。

逐字稿會自動過濾到相同範圍。影格時間戳是絕對的(真實影片時間軸,非從開始偏移)。

範例:

# 1 分鐘影片的最後 10 秒
python3 "${SKILL_DIR}/scripts/watch.py" video.mp4 --start 50 --end 60

# 聚焦 2:15 → 2:45,2 fps(60 影格)
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 2:15 --end 2:45 --fps 2

# 從 1h12m 到影片結束
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 1:12:00

步驟 3 — 讀取腳本列出的每個影格路徑。 Read 工具會直接將 JPEG 渲染為圖片供你查看。在單一訊息中讀取所有影格(平行工具呼叫),以便你同時看到它們。影格按時間順序排列,並帶有 t=MM:SS 時間戳,讓你可以將它們與逐字稿對齊。

步驟 4 — 回答使用者。 你現在有兩條證據流:

  • 影格 — 每個時間戳螢幕上的內容
  • 逐字稿 — 每個時間戳的說話內容。報告的標頭會顯示來源(captions = yt-dlp 拉取的原生字幕;whisper (groq)whisper (openai) = 由 API 轉錄)。

如果使用者問了特定問題,直接回答並引用時間戳。如果他們沒有問任何問題,總結影片中發生的事情 — 結構、關鍵時刻、 notable 視覺內容、口語內容。

這也適用於 transcript 詳細度:即使沒有影格,也要像其他模式一樣產生摘要 — 不要將完整逐字稿貼到對話中。綜合結構、關鍵時刻和帶時間戳的口語內容;只引用重要的行。僅在使用者明確要求時才提供原始逐字稿。

步驟 5 — 清理。 腳本會在結尾印出工作目錄。如果使用者不會對這個影片提出後續問題,用 rm -rf <dir> 刪除它。如果他們可能會,則保留它。

詳細度與影格

預設行為來自 ~/.config/watch/.env

  • WATCH_DETAIL=transcript|efficient|balanced|token-burner(預設:balanced

transcript 詳細度下,字幕足以回傳報告而無需下載影片。如果缺少字幕,腳本只下載音訊並嘗試 Whisper。如果無法產生逐字稿,它會清楚報告限制;使用 --detail balanced 重新執行以取得影格。

efficient 詳細度下,腳本下載影片並只提取關鍵影格ffmpeg -skip_frame nokey)— 一個近乎即時的過程,在場景切換處取得影格。如果剪輯少於 4 個關鍵影格,它會回退到均勻取樣。

balanced / token-burner 詳細度下,腳本提取場景感知影格:先使用 ffmpeg 場景變換選取,僅在影片實際上靜態時回退到均勻取樣。balanced 上限為 100 影格;token-burner 無上限。影格報告行包含時間戳和選取原因。提取的圖片高度上限為 1998px,以相容 Claude Read。

逐字稿提示影格

視覺影格選取(場景/關鍵影格)可能會錯過講者明確標記的時刻 — 「看這裡」、「如你所見」、「注意這個」、「看看會發生什麼」 — 因為指向投影片通常是視覺變化。--timestamps 讓你在那些確切時刻強制加入影格。透過閱讀逐字稿來決定哪些時刻重要:

  1. 先以 --detail transcript(或任何詳細度)執行一次,取得帶時間戳的逐字稿。
  2. 掃描指示性提示 — 講者引導注意力到螢幕上某處的片語。這需要判斷(忽略修辭性的「你看,重點是…」);這就是為什麼由你來做,而不是正規表達式。
  3. 使用 --timestamps 4:32,7:10,9:55 重新執行(絕對來源時間)。對於網址,將第二次執行指向工作目錄中的已下載本機檔案,這樣它就不會重新下載。

行為:

  • 預設為附加。 提示影格(reason=transcript-cue)會按時間順序合併到 --detail 已選取的影格中。
  • 優先保留並優先計數。 提示影格在詳細度引擎執行前就從影格上限中保留,因此它們永遠不會被均勻取樣排除。
  • 尊重聚焦模式。 使用 --start/--end 時,任何在視窗外的提示時間戳都會被丟棄(在摘要中報告)。座標永遠是絕對來源時間。
  • 僅提示影格。 --detail transcript --timestamps … 跳過場景/關鍵影格取樣,只回傳提示影格(它會下載影片來做到這一點,因為影格需要像素)。

轉錄

腳本透過兩種方式之一取得帶時間戳的逐字稿:

  1. 原生字幕(免費,較推薦)。 如果有的話,yt-dlp 會從來源平台拉取手動或自動產生的字幕。
  2. Whisper API 備援。 如果沒有回傳字幕(或來源是本機檔案),腳本會提取音訊(ffmpeg -vn -ac 1 -ar 16000 -b:a 64k,約 0.5 MB/分鐘)並上傳到已設定金鑰的 Whisper API:

兩個金鑰都存在 ~/.config/watch/.env 中。當兩者都設定時,腳本偏好 Groq;使用 --whisper openai 覆蓋以強制使用 OpenAI。使用 --no-whisper 完全跳過備援。

失敗模式與處理

  • 設定預檢失敗 → 執行 python3 "${SKILL_DIR}/scripts/setup.py"(在 macOS 上透過 brew 自動安裝 ffmpeg/yt-dlp,建立 .env)。對於 API 金鑰,透過 AskUserQuestion 詢問使用者並寫入 ~/.config/watch/.env
  • 沒有可用的逐字稿 → 缺少字幕且(沒有 Whisper 金鑰或 Whisper API 失敗)。腳本會印出指向設定的提示。僅以影格繼續並告知使用者。
  • 長影片警告印出 → 在你的回答中承認它。提議透過 --start/--end 重新執行聚焦於特定段落,而不是進行稀疏的全片掃描。
  • 下載失敗 → yt-dlp 的錯誤會輸出到 stderr。如果是需要登入或地區限制的影片,直接告訴使用者;不要一直重試。
  • Whisper 請求失敗 → 錯誤會印到 stderr(可能是:金鑰無效或速率限制)。超過 API 25 MB 上傳上限的音訊會自動分割成區塊並轉錄,所以長度本身不會導致失敗;如果某些區塊失敗,逐字稿會不完整,且丟棄的區塊會在 stderr 上註明。只有當所有區塊都失敗時,報告才會顯示「none available」。如果 Groq 失敗,你可以使用 --whisper openai 重試(反之亦然)。

Token 效率

這個技能主要消耗 token 在影格上。數量級:

  • 80 個 512px 寬的影格大約是 50-80k 圖片 token,取決於長寬比。
  • 逐字稿很便宜(10 分鐘的影片最多幾千個 token)。
  • --resolution 提高到 1024 大約會使每個影格的圖片 token 增加四倍。只在必要時才這麼做。

如果你在這個會話中已經看過影片,且使用者提出後續問題,不要重新執行腳本 — 你已經有影格和逐字稿在上下文中。直接根據你已有的內容回答。

安全性與權限

這個技能會做的事:

  • 在本機執行 yt-dlp 以下載影片並在來源支援時拉取原生字幕(公開資料;請求直接發送到網址指向的任何主機)
  • 在本機執行 ffmpeg / ffprobe 以提取 JPEG 影格,並在需要 Whisper 時提取單聲道 16 kHz 音訊片段
  • 當設定了 GROQ_API_KEY 時,將提取的音訊片段傳送到 Groq 的 Whisper API(api.groq.com/openai/v1/audio/transcriptions)(較推薦 — 更便宜、更快)
  • 當設定了 OPENAI_API_KEY 且未設定 Groq,或強制使用 --whisper openai 時,將提取的音訊片段傳送到 OpenAI 的音訊轉錄 API(api.openai.com/v1/audio/transcriptions
  • 將下載的影片、影格、音訊和中間逐字稿寫入系統暫存目錄下的工作目錄(或如果指定了 --out-dir),以便 Claude 可以 Read 它們
  • 讀取/建立 ~/.config/watch/.env(權限 0600)以儲存 Whisper API 金鑰和 SETUP_COMPLETE 標記。作為備援,也會讀取目前工作目錄中的 .env

這個技能不會做的事:

  • 不會將影片本身上傳到任何 API — 只有提取的音訊會傳出,且僅在缺少原生字幕且未使用 --no-whisper 停用 Whisper 時
  • 不會存取任何平台帳戶(無登入、無 session cookie、無發文)— yt-dlp 永遠只請求公開資料
  • 不會在提供者之間共用 API 金鑰(Groq 金鑰只傳送到 api.groq.com,OpenAI 金鑰只傳送到 api.openai.com
  • 不會記錄、快取或將 API 金鑰寫入 stdout、stderr 或輸出檔案
  • 不會在工作目錄和 ~/.config/watch/.env 之外保留任何東西 — 完成後清理工作目錄(步驟 5)

捆綁腳本: scripts/watch.py(進入點)、scripts/download.py(yt-dlp 包裝)、scripts/frames.py(ffmpeg 影格提取)、scripts/transcribe.py(字幕選取 + Whisper 編排)、scripts/whisper.py(Groq / OpenAI 客戶端)、scripts/setup.py(預檢 + 安裝程式)

首次使用前請檢閱腳本以驗證行為。