/watch
あなたには動画入力がありません。このスキルがそれを提供します。Python スクリプトがまずキャプションを取得し、必要に応じて動画をダウンロードし、フレームを JPEG として抽出(シーン認識、または efficient 詳細度の場合は高速キーフレーム)し、タイムスタンプ付き文字起こし(まずネイティブキャプション、次に Whisper API をフォールバックとして)を取得し、フレームパスを出力します。その後、各フレームパスを Read して画像を確認し、それらを文字起こしと組み合わせてユーザーに回答します。
SKILL_DIR の解決(すべてのコマンドの前に行うこと)
以下のすべての python3 ... コマンドは、SKILL_DIR/scripts/ にあるバンドルスクリプトを実行します。SKILL_DIR を、今 Read したこの SKILL.md が含まれているディレクトリの絶対パスに設定してください。ハーネスは 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} をそのリテラルパスに置き換えてください。これは、ハーネス固有の環境変数に依存せず、すべてのハーネス(Claude Code、Codex、Cursor、Gemini CLI など)で機能します。実行開始時に一度だけガードしてください:
SKILL_DIR="<Read した SKILL.md を含むディレクトリの絶対パス>"
if [ ! -f "$SKILL_DIR/scripts/watch.py" ]; then
echo "ERROR: SKILL_DIR=$SKILL_DIR の下に scripts/watch.py が見つかりません" >&2
echo "Read した 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
2 つのフィールドで分岐します:
can_proceed: trueかつfirst_run: false→ セットアップは既に完了しています(ユーザーが意図的に Whisper キーをスキップした可能性があります — それは許可されています)。コメントなしでステップ 1 に進みます。first_run: true→ 本当の初回セットアップです。次の順序で行います:missing_binariesが空でない場合、最初にインストーラーを実行します(macOS では自動インストール、その他の環境ではコマンドを出力します — 以下を参照)。バイナリが配置されたことを確認してください。これをスキップして設定に飛ばないでください。- 必要に応じてインストーラーをもう一度実行し、
~/.config/watch/.envをスキャフォールディングします(ファイルが存在しない場合のみテンプレートを書き込むため、値を書き込む 前に ファイルを作成させてください)。 - Whisper API キーを推奨し、以下の視聴設定に関する質問をしてから、選択された値を
~/.config/watch/.envに書き込み、SETUP_COMPLETE=trueを設定します。
can_proceed: falseかつfirst_run: false→ セットアップは以前に完了していましたが、環境が後退しました(例:OS 変更後の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"
Homebrew がインストールされている macOS では、ffmpeg と yt-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 を使用して 1 つの質問をします:
- デフォルトの詳細度(1 つのダイヤル)。これらを
AskUserQuestionオプションとしてこの正確な順序で提示します — 軽いものから重いものへ — そして(recommended)はbalancedに付けたままにします(最初に推奨オプションを置くために 並べ替えないでください):transcript— フレームなし、文字起こしのみ(キャプションが存在する場合、動画ダウンロードをスキップ)。efficient— 高速キーフレームパス(上限 50)。balanced(推奨) — シーン認識フレーム(上限 100、デフォルト)。token-burner— シーン認識、上限なし(最大忠実度、トークンコスト高)。
回答を直接 ~/.config/watch/.env に書き込みます。キーを単独の行に設定し、末尾のインラインコメントは付けません(値の後の # 注釈 は解析を壊す可能性があります):
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} を出力します。status は ready | needs_install | needs_key | needs_install_and_key のいずれかです。status は 理想的な 状態を説明します(キーは推奨されるため、キーなしの初回実行は needs_key と読み取られます)。can_proceed は運用上のゲートです(バイナリが存在する AND キーが設定されている、またはセットアップが既に完了している)。can_proceed/first_run で分岐して実行するかどうかを決定します。status を使用して何を推奨するかを決定します。
単一セッション内では、後続の /watch 呼び出しでステップ 0 をスキップできます — 一度 --check が 0 を返せば、ターン間で環境は変化しません。
使用するタイミング
- ユーザーが動画 URL(YouTube、Vimeo、X、TikTok、Twitch クリップ、yt-dlp 対応のほとんどのサイト)を貼り付けて、それについて尋ねた場合。
- ユーザーがローカル動画ファイル(
.mp4、.mov、.mkv、.webmなど)を指定して、それについて尋ねた場合。 - ユーザーが
/watch <url-or-path> [question]と入力した場合。
推奨上限
- 最高精度:10 分未満の動画。 フレームカバレッジは、時間に反比例します。
- 汎用レート上限:2 fps。 スクリプトは、予算や
--fpsがそれ以上の fps を示唆しても、2 fps より速くサンプリングすることはありません。 - フレーム上限は詳細モードによって設定されます(
~/.config/watch/.envのWATCH_DETAIL、または--detail)。単一のグローバル上限ではありません:transcript→ フレームなしefficient→ 最大 50(キーフレーム)balanced(デフォルト)→ 最大 100(シーン認識)token-burner→ 上限なし(シーン認識;250 フレームを超えるとソフト警告が出力されます)--max-frames Nは、モードが使用する上限をオーバーライドします。
- 時間による動画全体のフレーム予算。 トークンコストはフレーム数に比例して増加するため、スクリプトは時間に基づいて予算を設定します。この予算は fps と均一サンプリングのフォールバックを設定します。シーン認識による選択は、以下で説明する詳細上限(ただし、詳細上限を超えない)まで埋めることができます:
- ≤30秒 → ~12〜30 フレーム
- 30秒〜1分 → ~40 フレーム
- 1〜3分 → ~60 フレーム
- 3〜10分 → ~80 フレーム
-
10分 → 詳細上限まで、間隔を大きく空ける(警告が出力されます)
- ユーザーが長い動画を渡した場合は、トークンをまばらなスキャンに費やす前に、特定のセクションを希望するかどうかを検討してください。
呼び出し方
ステップ 1 — ユーザー入力を解析します。 動画ソース(URL またはパス)と、ユーザーが尋ねた質問を分離します。例:/watch https://youtu.be/abc what language is this in? → source = https://youtu.be/abc、question = what language is this in?。
ステップ 2 — 視聴スクリプトを実行します。 ソースをそのまま渡します。通常の引用符以外で自分でシェルエスケープしないでください:
python3 "${SKILL_DIR}/scripts/watch.py" "<source>"
オプションフラグ:
--detail transcript|efficient|balanced|token-burner— 忠実度/速度ダイヤル。transcript= フレームなし(文字起こしのみ、キャプションが存在する場合、動画ダウンロードをスキップ);efficient= 高速キーフレーム(上限 50);balanced= シーン認識フレーム(上限 100);token-burner= シーン認識、上限なし。--start T/--end T— セクションに焦点を当てます。SS、MM:SS、またはHH:MM:SSを受け入れます。いずれかが設定されている場合、fps はより密に自動スケーリングされます(以下の「セクションに焦点を当てる」を参照)。--timestamps T1,T2,…— これらの絶対タイムスタンプ(SS、MM:SS、またはHH:MM:SS)のそれぞれでフレームを取得します。文字起こしを読んだ後、これを使用して、発表者が指し示す指示的な瞬間(「ここを見てください」「ご覧のように」「これに注目」)をキャプチャします。これらは視覚的な選択だけでは見逃される可能性があります。以下の「文字起こしキューによるフレーム」を参照してください。--max-frames N— より厳しいトークン予算のために事前設定された上限をオーバーライドします(例:--max-frames 40)--resolution W— フレームの幅(ピクセル単位)を変更します(デフォルト 512;画面上のテキストを読む必要がある場合のみ 1024 に増やしてください)--fps F— 自動 fps をオーバーライドします(最大 2 fps に制限されます)--out-dir DIR— 作業ファイルを特定の場所に保持します(デフォルト:自動生成された tmp ディレクトリ)--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 します。 Read ツールは JPEG を直接画像としてレンダリングします。すべてのフレームを 1 つのメッセージで(並列ツールコールで)Read して、それらをまとめて確認できるようにします。フレームは時系列順に並び、t=MM:SS のタイムスタンプが付いているため、文字起こしと対応付けることができます。
ステップ 4 — ユーザーに回答します。 これで 2 つの証拠ストリームが得られました:
- フレーム — 各タイムスタンプでの画面上の内容
- 文字起こし — 各タイムスタンプで話されている内容。レポートのヘッダーにはソースが表示されます(
captions= yt-dlp がネイティブ字幕を取得;whisper (groq)またはwhisper (openai)= API によって文字起こし)。
ユーザーが特定の質問をした場合は、タイムスタンプを引用して直接回答します。何も質問しなかった場合は、動画の内容(構造、重要な瞬間、注目すべきビジュアル、話されている内容)を要約します。
これは transcript 詳細度にも当てはまります。フレームがなくても、他のモードと同様に 要約 を生成します。完全な文字起こしをチャットに貼り付けないでください。構造、重要な瞬間、およびタイムスタンプ付きの話された内容を合成し、重要な行のみを引用します。ユーザーが明示的に要求した場合にのみ、生の文字起こしを提供します。
ステップ 5 — クリーンアップします。 スクリプトは最後に作業ディレクトリを出力します。ユーザーがこの動画についてフォローアップの質問をしない場合は、rm -rf <dir> で削除します。する可能性がある場合は、そのままにしておきます。
詳細度とフレーム
デフォルトの動作は ~/.config/watch/.env から取得されます:
WATCH_DETAIL=transcript|efficient|balanced|token-burner(デフォルト:balanced)
(元の SKILL.md がこの時点で切り詰められているため、これ以降の内容は不明です。翻訳は提供された部分に基づいています。)