/watch
비디오 입력이 없어도 이 스킬이 제공합니다. Python 스크립트가 먼저 캡션을 가져오고, 선택적으로 비디오를 다운로드하며, JPEG 프레임(장면 인식 방식 또는 efficient 세부 수준에서는 빠른 키프레임 방식)을 추출하고, 타임스탬프가 포함된 트랜스크립트(기본 자막 우선, Whisper API 대체)를 생성한 후 프레임 경로를 출력합니다. 그런 다음 각 프레임 경로를 Read하여 이미지를 보고 트랜스크립트와 결합하여 사용자에게 답변합니다.
SKILL_DIR 설정 (모든 명령어보다 먼저 수행)
아래 모든 python3 ... 명령어는 SKILL_DIR/scripts/ 아래에 번들된 스크립트를 실행합니다. SKILL_DIR을 방금 Read한 이 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별 환경 변수에 의존하지 않고 모든 harness(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
두 필드에 따라 분기합니다:
can_proceed: true및first_run: false→ 설정이 이미 완료됨(사용자가 Whisper 키를 의도적으로 건너뛰었을 수 있음 — 허용됨). 1단계로 진행하고 언급하지 마세요.first_run: true→ 진정한 첫 실행 설정입니다. 순서대로 수행하세요:missing_binaries가 비어 있지 않으면 먼저 설치 프로그램을 실행하세요(macOS에서 자동 설치 / 다른 OS에서는 명령어 출력 — 아래 참조)하고 바이너리가 설치되었는지 확인하세요. 이 단계를 건너뛰고 설정으로 바로 가지 마세요.- 필요하면 설치 프로그램을 한 번 더 실행하여
~/.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단계에서 사용자에게 보이는 유일한 출력은 복구가 필요할 때만입니다.
종료 코드가 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에서는 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을 사용하여 한 가지 질문을 하세요:
- 기본 세부 수준(한 가지 선택). 다음 옵션을 정확히 이 순서로 — 가장 가벼운 것부터 무거운 것까지 —
AskUserQuestion옵션으로 제시하고,balanced에(recommended)를 유지하세요(첫 번째가 아니더라도 순서를 바꾸지 마세요):transcript— 프레임 없음, 트랜스크립트만(캡션이 있으면 비디오 다운로드 생략)efficient— 빠른 키프레임 패스(최대 50)balanced(권장) — 장면 인식 프레임(최대 100, 기본값)token-burner— 장면 인식, 무제한(최대 충실도, 토큰 비용 높음)
답변을 ~/.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}을 출력하며, status는 ready | needs_install | needs_key | needs_install_and_key 중 하나입니다. status는 이상적인 상태를 설명하고(키가 권장되므로 키 없는 첫 실행은 needs_key로 읽힘); can_proceed는 운영 게이트입니다(바이너리가 있고 키가 설정되었거나 설정이 이미 완료됨). 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분 미만 비디오. 프레임 커버리지는 길이에 반비례합니다.
- 범용 속도 제한: 2fps. 스크립트는 예산이나
--fps가 더 높은 속도를 의미하더라도 2fps보다 빠르게 샘플링하지 않습니다. - 프레임 상한은 세부 수준 모드에 따라 설정됩니다(
~/.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단계 — watch 스크립트를 실행합니다. 소스를 그대로 전달하세요. 일반 인용 이상으로 셸 이스케이프를 직접 수행하지 마세요:
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— 프레임 너비를 px 단위로 변경(기본값 512; 사용자가 화면의 텍스트를 읽어야 하는 경우에만 1024로 증가)--fps F— 자동 fps 재정의(최대 2fps로 제한됨)--out-dir DIR— 작업 파일을 특정 위치에 유지(기본값: 자동 생성된 임시 디렉토리)--whisper groq|openai— 특정 Whisper 백엔드 강제(기본값: 두 키가 모두 있으면 Groq 선호)--no-whisper— Whisper 대체를 완전히 비활성화(캡션이 없으면 프레임만)--no-dedup— 거의 중복된 프레임 유지. 기본적으로 프레임 델타 패스는 이전에 유지된 프레임과 시각적으로 거의 동일한 프레임(고정 슬라이드, 정적 화면 녹화, 일시 정지된 비디오)을 드롭하여 프레임 예산이 고유한 콘텐츠에 사용되도록 합니다. 보고서의 Frames 줄에 드롭된 프레임 수가 표시됩니다. 사용자가 모든 샘플링된 프레임이 필요한 경우에만 전달하세요(예: 미세한 프레임 간 움직임 판단).
특정 부분 집중(더 높은 프레임 속도)
사용자가 특정 순간에 대해 질문할 때 — "2분 표시에서 무엇이 발생하나요?", "0:45에서 1:00으로 확대", "처음 10초" — --start 및/또는 --end를 전달하세요. 스크립트는 집중 모드 예산으로 전환하며, 이는 전체 비디오 예산보다 더 조밀합니다(여전히 2fps로 제한되고 세부 수준 모드 상한에 의해 제한됨 — 아래 개수는 기본 balanced 상한 100을 가정함; efficient는 최대 50):
- ≤5초 → 2fps (최대 10프레임)
- 5-15초 → 2fps (최대 30프레임)
- 15-30초 → ~2fps (최대 60프레임)
- 30-60초 → ~1.3fps (최대 80프레임)
- 60-180초 → ~0.6fps (100프레임, 상한)
집중 모드는 다음 경우에 적합한 선택입니다:
- 사용자가 명시적으로 명명한 모든 순간/범위("2:30쯤", "인트로", "마지막 30초").
- 약 10분보다 긴 비디오에서 사용자의 질문이 특정 부분에 관한 경우 — 관련 부분에 집중하여 실행하는 것이 전체 비디오를 드물게 스캔하는 것보다 훨씬 유용합니다.
- 전체 스캔 후 특정 영역에 충분한 세부 정보가 없었던 재실행.
트랜스크립트는 동일한 범위로 자동 필터링됩니다. 프레임 타임스탬프는 절대적입니다(실제 비디오 타임라인, 시작 오프셋 아님).
예시:
# 1분 비디오의 마지막 10초
python3 "${SKILL_DIR}/scripts/watch.py" video.mp4 --start 50 --end 60
# 2:15 → 2:45를 2fps로 확대(60프레임)
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 2:15 --end 2:45 --fps 2
# 1시간 12분부터 비디오 끝까지
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 1:12:00
3단계 — 스크립트가 나열한 모든 프레임 경로를 Read합니다. Read 도구는 JPEG를 직접 이미지로 렌더링합니다. 모든 프레임을 단일 메시지(병렬 도구 호출)로 읽어 함께 볼 수 있도록 하세요. 프레임은 시간 순서대로 있으며 t=MM:SS 타임스탬프가 있어 트랜스크립트와 정렬할 수 있습니다.
4단계 — 사용자에게 답변합니다. 이제 두 가지 증거 스트림이 있습니다:
- 프레임 — 각 타임스탬프에서 화면에 보이는 내용
- 트랜스크립트 — 각 타임스탬프에서 말한 내용. 보고서 헤더에는 소스가 표시됩니다(
captions= yt-dlp가 가져온 기본 자막;whisper (groq)또는whisper (openai)= API로 전사).
사용자가 특정 질문을 한 경우 타임스탬프를 인용하여 직접 답변하세요. 질문을 하지 않은 경우 비디오에서 발생하는 일 — 구조, 주요 순간, 주목할 만한 시각 자료, 음성 내용을 요약하세요.
이는 transcript 세부 수준에도 적용됩니다: 프레임이 없더라도 다른 모드와 마찬가지로 요약을 생성하세요 — 전체 트랜스크립트를 채팅에 붙여넣지 마세요. 타임스탬프와 함께 구조, 주요 순간, 음성 내용을 종합하고 중요한 줄만 인용하세요. 원시 트랜스크립트는 사용자가 명시적으로 요청하는 경우에만 제공하세요.
5단계 — 정리합니다. 스크립트는 마지막에 작업 디렉토리를 출력합니다. 사용자가 이 비디오에 대한 후속 질문을 하지 않을 경우 rm -rf <dir>로 삭제하세요. 질문할 가능성이 있으면 그대로 두세요.
세부 수준 및 프레임
기본 동작은 ~/.config/watch/.env에서 가져옵니다:
WATCH_DETAIL=transcript|efficient|balanced|token-burner(기본값:balanced)
--detail로 재정의합니다.