영상을 보는 눈을 달아주는 /watch 스킬플러그인
03ceb42f7fa2c4439aca01752118044baabffb8f의 소스 검토이며 실제 영상 처리나 모델 호출 결과가 아닙니다./watchclaude-video는 "LLM에게 영상을 입력으로 넣어주는" Claude Code 플러그인/Agent Skill이다. 원래 Claude 같은 모델은 이미지는 볼 수 있어도 동영상은 직접 못 본다. 이 스킬은 그 벽을 우회한다 — 영상을 "여러 장의 사진(프레임) + 시간표가 붙은 대본(transcript)"으로 변환해, Claude가 원래 잘 다루는 "이미지 읽기 + 텍스트 이해"로 문제를 바꿔치기한다.
사용법은 슬래시 명령 한 줄이다. /watch <URL 또는 파일경로> [질문] 을 입력하면, 뒤에서 파이썬 스크립트가 다운로드→프레임 추출→대본 생성을 자동으로 처리하고, 그 결과를 Claude가 받아 "영상을 실제로 본 것처럼" 대답한다. 코드는 100% 파이썬 표준 라이브러리로만 쓰여 있어 pip install이 필요 없다(대신 ffmpeg·yt-dlp 같은 시스템 도구는 있어야 한다).
Claude는 사진과 글은 잘 읽지만 동영상 파일은 못 여는 친구와 같다. 그 친구에게 영상 내용을 물어보려면? 영상을 대신 재생해서 중요한 장면을 사진으로 캡처하고, 대사를 시간과 함께 받아쓴 다음, "여기 사진 20장이랑 대본이야, 이거 보고 질문에 답해줘"라고 건네면 된다.
claude-video가 하는 일이 정확히 이것이다. 영상 자체를 AI에게 던지는 게 아니라, AI가 이미 잘 다루는 형태(이미지 + 타임스탬프 텍스트)로 번역해서 넘긴다. 그래서 "영상 이해"라는 어려운 문제가 "사진 여러 장 보기"라는 이미 풀린 문제로 바뀐다.
SKILL.md라는 설명서 + 실제로 실행할 스크립트로 구성된다. claude-video의 경우 SKILL.md가 "영상을 보려면 이 파이썬 스크립트를 이렇게 호출하라"고 Claude에게 지시하는 사용설명서 역할을 한다.[01:23] …)와 함께 받아쓴 대본이다. 이 둘이 Claude에게 넘어가는 "영상의 요약본"이 된다.2026년의 AI 코딩 에이전트는 텍스트·이미지·PDF까지 척척 다루지만, 동영상 앞에서는 여전히 장님이다. "이 버그 재현 영상 좀 봐줘", "이 강의에서 그 부분이 몇 분이야?", "이 화면 녹화에서 UI가 언제 깨져?" 같은 일상적 요청을 처리 못 한다. claude-video는 이 정확한 빈틈을, 새 모델이나 거창한 인프라 없이 기존 도구를 영리하게 엮어 메운다. (TrendShift의 굵은 숫자는 별 개수가 아니라 사회적 언급 모멘텀 점수다.)
프레임과 대본으로 입력을 나누는 local 경로는 호스트의 이미지·텍스트 읽기를 활용합니다. 0.3 계열은 여기에 외부 영상 모델의 답변을 받는 경로를 더했습니다. 둘의 결과를 같은 종류의 관찰로 취급하지 않는 점이 학습할 부분입니다.
파이썬 서드파티 패키지가 단 하나도 없다. Groq/OpenAI SDK조차 안 쓰고 표준 라이브러리 urllib로 직접 API를 호출한다. 덕분에 /plugin install watch@claude-video 한 줄이면 끝이고, 감사(audit)·이식도 쉽다. "당장 오늘 내 Claude Code에 붙여볼 수 있다"는 접근성이 확산을 도왔다.
영상을 프레임으로 다 넘기면 Claude의 컨텍스트(그리고 비용)가 폭발한다. claude-video는 이를 알고 프레임 수를 "예산"으로 관리한다 — 길이별로 목표 프레임 수를 정하고, 장면 전환만 잡고, 비슷한 프레임은 지우고, 최대 개수로 clamp한다. 4가지 상세 모드(transcript/efficient/balanced/token-burner)로 "정확도 ↔ 토큰 비용"을 사용자가 고를 수 있게 한 점이 실용적이다.
로컬 엔진은 네이티브 자막을 먼저 읽고, 없을 때 사용자가 정한 음성 인식 경로를 사용합니다. 0.3 계열에는 영상을 Google로 보내 답변받는 Gemini 엔진과 선택적인 로컬 WhisperX가 추가됐습니다. 엔진 선택에 따라 데이터가 이동하는 곳과 준비 조건이 달라집니다.
핵심 Python 오케스트레이터는 표준 라이브러리를 사용합니다. 선택 WhisperX 환경은 별도 Python 패키지·모델을 설치하므로 저장소 전체 사용 조건을 “pip 의존성 0개”로 요약하면 부정확합니다.
| 경로 | 입력 처리 | 조건 |
|---|---|---|
| local | 로컬 프레임·자막을 호스트 에이전트에 전달 | Python 3.10+, FFmpeg/ffprobe, URL에는 최신 yt-dlp와 사이트별 접근 조건 |
| gemini | YouTube URL 또는 Files API로 보낸 영상에 대해 Google이 답변 | Gemini API 키. YouTube 직접 경로에는 로컬 미디어 도구 불필요 |
| 선택 WhisperX | 자막이 없을 때 로컬 CPU 음성 인식 | uv의 별도 Python 3.12 환경·WhisperX 3.8.6·모델 캐시 |
| 선택 Groq/OpenAI | 자막이 없을 때 오디오를 해당 API에 전송 | 사용자가 선택한 경로와 키. 자막만 모드도 가능 |
--engine auto는 키가 있으면 Gemini를 선택할 수 있습니다. 로컬 프레임을 직접 확인하려면 --engine local을 명시합니다. local만으로 음성의 클라우드 전송까지 꺼지지는 않으므로 자막만 쓸 때는 --no-whisper도 사용합니다.
run_gemini()는 실패를 보고하고 로컬 엔진으로 조용히 바꾸지 않습니다. finally에서 업로드 삭제를 시도하지만 실패 경고가 남을 수 있으므로 “항상 삭제됨”으로 단정할 수 없습니다. 반환된 관찰은 Gemini의 답변이며 호스트가 직접 본 프레임이라고 표시하지 않습니다.
local_whisperx.py는 설정한 절대 실행 파일과 .deps-ok를 확인하고, 별도 프로세스의 제한된 진단 출력을 읽습니다. 시간 초과·취소 때 자식 프로세스를 종료하고, 실패해도 클라우드로 바꾸지 않습니다. 기본 small 모델·CPU/int8·batch 8은 설정값이며 모든 하드웨어에서 같은 성능을 뜻하지 않습니다.
watch.py는 프레임·대본 중 무엇이 준비됐는지와 무음·부분 증거·사용 불가 상태를 표시합니다. 균등 샘플링 같은 프레임 내부 대체 경로는 남아 있지만 엔진이나 전송 대상을 바꾸는 동작과 구분해야 합니다.
# 독자용 예시: 로컬 영상의 화면만 확인
python3 skills/watch/scripts/watch.py example.mp4 \
--engine local --no-whisper --detail balanced
위 명령은 이 루틴에서 실행하지 않았습니다. 이미지 파일 경로를 호스트에 넘기는 local 경로와 Google의 답변을 중계하는 gemini 경로는 서로 다른 증거입니다.
핵심은 여전히 자기완결적인 skills/watch/입니다. README 0.3.2는 Claude Chat·Cowork의 지원 안내를 제거했습니다. 저장소에 묶음 빌드 도구가 있다는 사실만으로 모든 업로드 환경을 지원한다고 볼 수는 없습니다.
이 저장소의 교육 가치는 크게 두 갈래다 — (A) 에이전트/스킬 엔지니어링(LLM의 능력을 어떻게 확장하나)과 (B) 실전 파이썬·미디어 처리(subprocess·ffmpeg·API를 견고하게 다루는 법). 기술별로 정리한다.
claude-video의 핵심 교훈은 "모델이 못하는 일을, 모델이 잘하는 일로 바꿔라"다. 영상 이해(어려움)를 이미지 읽기+텍스트 이해(쉬움)로 번역했다. 이 변환 발상은 다른 곳에도 응용된다 — PDF를 이미지로, 오디오를 대본으로, 웹페이지를 마크다운으로. "새 모델을 기다리지 말고, 지금 모델이 소화할 형태로 입력을 가공하라"는 사고법을 배운다.
download.py는 yt-dlp를 subprocess로 호출하며 실전 노하우가 가득하다: 인자에 --를 넣어 URL을 옵션과 분리(옵션 인젝션 방지), -로 시작하는 입력 거부, 그리고 성공 판정을 "종료코드"가 아니라 "결과 파일이 실제로 생겼나"로 한다(자막 다운로드가 429로 실패해도 영상만 있으면 성공). 외부 CLI를 코드에서 부릴 때 마주치는 현실 문제와 그 해법을 보여준다.
whisper.py는 groq/openai SDK를 쓰지 않고 urllib.request로 multipart/form-data body를 손으로 조립해 파일을 업로드한다. HTTP가 실제로 어떻게 파일을 실어 나르는지, boundary가 뭔지 밑바닥부터 이해하게 된다. 덤으로 Cloudflare WAF에 막히지 않으려 정직한 커스텀 User-Agent를 붙이는 실전 디테일(watch-skill/1.0 …)까지 배운다.
frames.py는 ffmpeg의 강력한 필터를 실전 활용한다: select='gt(scene,0.20)'로 장면 전환 검출, -skip_frame nokey로 I-프레임(키프레임)만 디코드해 ~40배 빠르게, scale 필터로 해상도·종횡비 clamp, showinfo로 각 프레임의 타임스탬프 복원. "영상에서 의미 있는 순간만 뽑는" 미디어 처리의 정석을 코드로 익힌다.
네트워크·외부 API를 다루는 코드가 갖춰야 할 견고성이 다 있다. 지수 백오프 재시도(429는 Retry-After 존중, 4xx는 즉시 포기), 크기 초과 시 청킹(25MB 넘는 오디오를 시간 균등 분할 후 재봉합), 부분 실패 허용(청크 일부 실패해도 진행). "해피 패스만 짜지 말고 실패를 설계하라"를 실물로 배운다.
tests/conftest.py는 유튜브나 API에 의존하지 않는다. ffmpeg로 "14색 하드컷 클립"·"단색 정적 클립"을 합성해 픽스처로 쓴다. 그래서 장면검출·키프레임·중복제거·폴백이 인터넷 없이 언제나 같은 결과로 검증된다. "외부 의존을 테스트에서 걷어내는" 방법의 좋은 사례다.
SKILL.md는 Claude Code 전용 변수(${CLAUDE_SKILL_DIR})에 의존하지 않고, 모델이 방금 읽은 SKILL.md의 위치를 기준으로 스크립트 경로를 잡는다. 덕분에 Codex·Cursor 어디서든 동작한다. git archive + .gitattributes export-ignore로 런타임 불필요 파일을 번들에서 빼는 것도 배포 노하우다.
| 기능 | 요구사항·한계 |
|---|---|
| 공통 Python 코드 | README 기준 Python 3.10 이상 |
| local 미디어 | FFmpeg·ffprobe, URL에는 최신 yt-dlp. YouTube에는 지원 JavaScript 런타임/EJS 준비도 확인 |
| 로컬 음성 인식 | 별도 Python 3.12 환경과 WhisperX 3.8.6. small은 진단 안내 기준 시스템 RAM 8GB 이상. CUDA 경로는 소스에서 미검증으로 표시 |
| Gemini YouTube 경로 | 키·Google 접근 가능성이 필요. 로컬 영상 등은 업로드됨 |
| 자막·클라우드 음성 인식 | 자막만 모드에는 음성 인식 키 불필요. Groq·OpenAI 선택 시 해당 서비스 조건 적용 |
GPU가 공통 필수인 것은 아니지만 로컬 WhisperX는 CPU·RAM·모델 캐시를 사용합니다. 에이전트가 클라우드 환경에서 실행되면 사용자의 Mac에 설치된 도구를 그대로 사용할 수 없습니다. 영상·오디오의 전송 경로는 엔진·음성 설정을 함께 확인하세요.
ffmpeg·yt-dlp를 깔고 스킬을 설치한 뒤, 자막이 있는 강의 영상 URL에 /watch <URL> --engine local --no-whisper --detail transcript를 시켜보자. Whisper 키 없이도 대본이 나오는지, Claude가 타임스탬프를 인용해 답하는지 확인 — 캡션 우선 경로가 체감된다.
같은 영상에 --engine local --no-whisper를 지정하고 --detail transcript / efficient / balanced / token-burner를 각각 걸고, 프레임 수·소요 시간·토큰 사용량이 어떻게 달라지는지 표로 적어보자. "정확도 ↔ 비용" 트레이드오프를 숫자로 만나면, 왜 예산 관리가 중요한지 몸으로 안다.
frames.py의 SCENE_THRESHOLD = 0.20을 0.10이나 0.40으로 바꿔 프레임 수가 어떻게 변하는지 실험하자. 임계치를 낮추면 사소한 변화도 컷으로 잡히고, 높이면 큰 전환만 남는다. ffmpeg의 scene 검출이 실제로 어떻게 동작하는지 감이 잡힌다.
ffmpeg로 아무 영상의 프레임 몇 장을 16×16 흑백으로 뽑고, claude-video처럼 평균 절대차로 근접 중복을 걸러내는 미니 스크립트를 짜보자. 임계치를 바꿔가며 "몇 이하를 같다고 볼까"를 조율하면, 라이브러리 없는 지각적 해싱의 원리를 손에 넣는다.
claude-video의 구조를 본떠, LLM이 못 다루는 다른 입력을 변환하는 스킬을 설계해보자 — 예: "긴 오디오 팟캐스트 → 챕터별 요약 대본", "복잡한 스프레드시트 → 이미지 차트 + 표 텍스트". SKILL.md(지시서) + 변환 스크립트 + 사전점검(setup.py 흉내) 구조를 그대로 빌리면, "입력 번역으로 능력을 확장"하는 이 레포의 핵심 역량이 내 것이 된다.
| 주차 | 주제 | 핵심 질문 · 자료 |
|---|---|---|
| 1주차 | 스킬/에이전트 엔지니어링 | SKILL.md로 에이전트에게 절차를 어떻게 가르치나. 경로 독립성·멀티 하네스 배포. → SKILL.md·AGENTS.md 정독 + Claude Code/Codex 스킬 문서. |
| 2주차 | 미디어 처리 (ffmpeg) | 필터 그래프, 장면검출(select=scene), 키프레임(-skip_frame nokey), 스케일·타임스탬프. → frames.py 정독 + ffmpeg 공식 필터 문서. |
| 3주차 | subprocess · HTTP 밑바닥 | 외부 CLI 안전 호출(인젝션 방지), urllib로 multipart 업로드, 재시도·백오프. → download.py·whisper.py 정독. |
| 4주차 | 견고성 · 테스트 설계 | 폴백 사슬, 청킹, 부분실패 허용, 네트워크 없는 결정론적 테스트. → transcribe.py·tests/conftest.py + 직접 픽스처 작성. |
먼저 watch.py를 위에서 아래로 읽어 전체 흐름(다운로드→프레임→대본→출력)을 머릿속에 그려라 — 이게 지도다. 그다음 가장 재밌는 frames.py의 한 상수(SCENE_THRESHOLD·MAX_FPS)를 바꿔 결과가 어떻게 달라지는지 실험하면, 각 설계 선택의 "왜"가 이해된다. 마지막으로 이 구조를 본떠 내가 원하는 다른 입력(오디오·문서·데이터)을 LLM용으로 번역하는 스킬을 만들어보면, 이 레포의 진짜 역량("입력을 가공해 능력을 확장")이 손에 남는다. 미디어 처리 경험이 없어도 좋다 — 이 레포는 ffmpeg의 어려운 기능을 딱 필요한 만큼만 쓰는 좋은 본보기다.
claude-video는 "AI 스킬" 물결의 한 갈래다. bradautomates의 다른 작업들처럼 "Claude에게 새 능력을 붙이는" 계열이고, 같은 트렌딩 목록의 Graphify-Labs/graphify·Egonex-AI/Understand-Anything은 "코드를 지식 그래프로 번역"해 에이전트에게 먹이는 사촌이다. 밑바닥 도구로 보면 yt-dlp(만능 다운로더)와 ffmpeg(미디어 스위스 army knife), Whisper(음성인식)가 이 스킬이 올라선 어깨다. 이들을 나란히 보면 "LLM에게 무엇을, 어떤 형태로 먹일 것인가"의 서로 다른 답이 보인다.
SKILL.md(지시서) + 실행 스크립트로 구성. claude-video는 "영상 보려면 이 파이썬을 이렇게 호출하라"를 SKILL.md에 적어둔다.select='gt(scene,0.20)' 필터로 구현. 덕분에 "말하는 사람이 가만있는" 지루한 구간을 건너뛰고 의미 있는 프레임만 뽑는다.-skip_frame nokey로 키프레임만 디코드하면 전체를 풀지 않아 ~40배 빠르다(efficient 모드).transcribe.py가 "이전 줄의 확장이면 병합"하는 규칙으로 이를 정리한다.urllib로 이 body를 손수 조립해 오디오를 Whisper API로 올린다. "파일 업로드가 실제로 어떻게 동작하나"를 밑바닥부터 보여준다.config.py가 모드별 프레임 상한을 정한다.2026-10-27 재검토 소스: 03ceb42f7fa2c4439aca01752118044baabffb8f. 설치·외부 모델 호출·실행 없이 아래 파일을 대조했습니다.
README.md · CHANGELOG.md · skills/watch/scripts/watch.py · skills/watch/scripts/gemini.py · skills/watch/scripts/local_whisperx.py · skills/watch/scripts/runtime.py
| 구분 | 링크 / 위치 |
|---|---|
| GitHub 저장소 | github.com/bradautomates/claude-video |
| TrendShift | trendshift.io/repositories/30967 |
| 설치 (Claude Code) | /plugin marketplace add bradautomates/claude-video → /plugin install watch@claude-video |
| 설치 (Codex/Cursor/기타) | npx skills add bradautomates/claude-video -g |
| 핵심 파일 | skills/watch/scripts/watch.py (진입점 393줄) |
| 핵심 파일 | skills/watch/scripts/frames.py (프레임 엔진 756줄 · auto-fps·장면검출·중복제거) |
| 핵심 파일 | skills/watch/scripts/whisper.py (stdlib Whisper 클라이언트 480줄) |
| 계약서 | skills/watch/SKILL.md (Claude 호출 규약 · 경로 독립성) |
| 이웃 프로젝트 | Graphify-Labs/graphify · Egonex-AI/Understand-Anything · yt-dlp · ffmpeg · openai/whisper |
| 연관 개념 | Agent Skill · 멀티모달 · 프레임 예산 · 장면검출 · STT/Whisper · graceful degradation |