coreyhaines31/makerskills

watch-video

When you want to extract content from a video — YouTube, Loom, Vimeo, Riverside, Zoom recording, local MP4, X/IG video, anything yt-dlp supports.

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/coreyhaines31/makerskills --skill watch-video

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

/watch-video — Transcribe and analyze any video at the depth you choose

Replaces and broadens the prior youtube-transcript skill. YouTube is now one of many sources; depth is user-controlled.

Step 1 — Parse input

Accept:

  • YouTube: full URL, youtu.be/<id>, youtube.com/shorts/<id>, raw 11-char ID
  • Loom: loom.com/share/<id> or loom.com/embed/<id>
  • Vimeo: vimeo.com/<id>
  • Riverside: download URL or local file
  • Zoom: local .mp4 from a downloaded recording
  • X / IG / TikTok video: URL — defers to social-fetch for metadata, uses yt-dlp for the file
  • Local file: any path to an .mp4 / .mov / .webm / .mkv

Detect source from URL pattern or file extension. If ambiguous, ask.

Step 2 — Parse depth mode

InvocationModeWhat you get
/watch-video <url>transcript (default)Clean text, metadata, optional chapters
/watch-video <url> transcripttranscriptSame as default
/watch-video <url> visualvisualTranscript + frames at intervals + Claude vision pass identifying key moments
/watch-video <url> multimodalmultimodalNative video to Gemini (if $GEMINI_API_KEY), else dense Claude vision frame-by-frame

If the depth isn't specified and the video is >10 minutes, ask before defaulting (visual/multimodal cost real money on long videos).

Step 3 — Pull metadata

For URL sources, use yt-dlp:

bash
yt-dlp --print "%(title)s|%(uploader)s|%(duration_string)s|%(upload_date>%Y-%m-%d)s|%(description)s" \
  --print "%(chapters)j" --skip-download "<url>"

Capture: title, uploader/channel, duration, upload date, description (first paragraph), chapters (JSON or null).

For local files, use ffprobe:

bash
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "<file>"

Step 4 — Build workdir

~/Documents/videos/<source>-<slug>-<date>/

Where:

  • source: youtube / loom / vimeo / riverside / zoom / local
  • slug: kebab-case of title (first 4–6 words, max 50 chars)
  • date: YYYY-MM-DD

Step 5 — Get the transcript

Backend selection (in order):

  1. Platform-provided transcript if it exists and looks complete:
  • YouTube: yt-dlp --write-sub --write-auto-sub --skip-download --sub-lang en --sub-format vtt
  • Loom: fetch via https://www.loom.com/share/<id> page metadata or Loom API if $LOOM_API_KEY set
  • Riverside: built-in transcripts available on the recording's share page
  • If platform transcript exists and has timestamps, use it. Skip Whisper.
  1. MLX-Whisper local (default on Apple Silicon Macs):
bash
   # Install once: pip install mlx-whisper
   python3 -c "import mlx_whisper; mlx_whisper.transcribe('<file>', path_or_hf_repo='mlx-community/whisper-large-v3-turbo')" \
     > "<workdir>/transcript-raw.json"

Or via the CLI: mlx_whisper <file> --model mlx-community/whisper-large-v3-turbo --output-dir <workdir>

  1. Not on Apple Silicon (Linux, Intel Mac, Windows, cloud agents): faster-whisper (pip install faster-whisper, CPU or CUDA) or whisper.cpp. Same model size, same output handling.

Download the video file first if it's a URL (use yt-dlp; Loom/Vimeo/YT all supported):

bash
yt-dlp -f "bv*[height<=720]+ba/b[height<=720]" -o "<workdir>/video.%(ext)s" "<url>"

720p is plenty for transcription and frame analysis (smaller download, faster processing).

Clean the transcript (only needed for YouTube auto-subs which have rolling captions; Whisper output is already clean):

bash
# YouTube VTT cleanup — de-dup rolling captions, strip tags, paragraph-break on cue gaps >2s
awk '
  /^WEBVTT/ || /^Kind:/ || /^Language:/ || /^NOTE/ { next }
  /-->/ { in_cue = 1; last = ""; next }
  /^$/ { if (last) print last; in_cue = 0; last = ""; next }
  in_cue { gsub(/<[^>]+>/, "", $0); last = $0 }
  END { if (last) print last }
' "<workdir>/transcript.en.vtt" | awk '!seen[$0]++' > "<workdir>/transcript.txt"

Save final to <workdir>/transcript.txt.

Step 6 — If transcript mode: stop here

Output:

  • transcript.txt
  • metadata.json
  • One-line summary in chat: title, source, duration, word count
  • Path to workdir
  • (Optional) Step 9 — offer to capture to second-brain

Step 7 — If visual mode: extract frames + vision pass

Frame extraction (ffmpeg)

Cadence by source heuristic:

Source typeFrame cadence
Screen-share / Loom / demo1 frame per 5s (UI changes fast)
Talking head / podcast1 frame per 30s (slow change)
Slide presentation1 frame per 10s + force a frame on each detected scene change
Default if unsure1 frame per 15s
bash
mkdir -p "<workdir>/frames"
ffmpeg -i "<workdir>/video.mp4" -vf "fps=1/15" "<workdir>/frames/frame-%04d.png" -y

For scene-change detection (slide decks especially):

bash
ffmpeg -i "<workdir>/video.mp4" -vf "select='gt(scene,0.3)',showinfo" -vsync vfr "<workdir>/frames/scene-%04d.png" 2> "<workdir>/scene-detection.log"

Vision pass

Pair each frame with the transcript chunk for the same timestamp window. Then batch-send to Claude vision for synthesis.

Per-frame batch prompt (up to ~10 frames per call):

Here are N frames from a video at timestamps T1..TN. For each frame, describe what's on screen in 1–2 sentences. Flag: (a) UI changes from previous frame, (b) text visible on screen, (c) any moment that looks like a decision, action, or notable event. Also note the transcript text spoken during this window.

Save the output as <workdir>/moments.md:

markdown
# Key moments — <title>

## 00:00:15 (frame-001.png)
**On screen**: Login form, email field focused
**Transcript**: "So you just open it up and..."
**Note**: Beginning of UI demo

## 00:00:45 (frame-002.png)
**On screen**: Dashboard with 4 cards
**Transcript**: "And here's where you see all your projects."
**Note**: Major view change — first time the dashboard appears

Generate summary

After moments are identified, synthesize the whole video into <workdir>/summary.md:

markdown
# Summary — <title>

**Source:** <source URL / file>
**Duration:** <hh:mm:ss>
**Watched at:** <date>
**Mode:** visual

## TL;DR
<2–4 sentences>

## Key moments
- 00:00:15 — <one-line>
- 00:00:45 — <one-line>

## Action items flagged
- <item> [timestamp]

## Decisions flagged
- <decision> [timestamp] — consider routing to /decide

## Quotes worth keeping
- "..." [timestamp]

## Open questions
- <question raised but not answered>

Step 8 — If multimodal mode

Backend selection

  1. Gemini native if $GEMINI_API_KEY is set (much cheaper + faster than per-frame for long videos):

Default model: `gemini-3.5-flash` (released May 2026, ~$1.50 input / $9 output per 1M tokens; ~$0.15/sec of video; beats 3.1 Pro on coding/agentic benchmarks at 4× the speed). Override to gemini-3.1-pro for brand audits / high-stakes analysis where details matter; gemini-2.5-flash-lite for bulk cheap processing.

bash
   # Step 1: Upload video via Files API
   FILE_URI=$(curl -s -X POST "https://generativelanguage.googleapis.com/upload/v1beta/files?key=$GEMINI_API_KEY" \
     -H "X-Goog-Upload-Command: start, upload, finalize" \
     -H "Content-Type: video/mp4" \
     --data-binary "@<workdir>/video.mp4" | jq -r '.file.uri')

   # Wait until file is ACTIVE (Gemini processes the video first)
   while true; do
     STATE=$(curl -s "$FILE_URI?key=$GEMINI_API_KEY" | jq -r '.state')
     [ "$STATE" = "ACTIVE" ] && break
     sleep 3
   done

   # Step 2: Generate content with the file + multimodal-analysis prompt
   curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key=$GEMINI_API_KEY" \
     -H "Content-Type: application/json" \
     -d "{
       \"contents\":[{
         \"parts\":[
           {\"file_data\":{\"mime_type\":\"video/mp4\",\"file_uri\":\"$FILE_URI\"}},
           {\"text\":\"<multimodal analysis prompt — see Step 7's summary template + use-case extensions>\"}
         ]
       }]
     }"

Files persist in Gemini Files API for ~48 hours — useful for re-querying the same video with different prompts.

  1. Dense Claude vision fallback if no Gemini key:
  • Frame cadence: 1 frame per 3s (much denser than visual mode)
  • Batch through Claude vision with the multimodal-analysis prompt
  • Slower and more expensive than Gemini for long videos — warn the user before running on >10min content

Multimodal output

Same summary.md template as Step 7 + an extended section:

markdown
## Multimodal observations
- **Body language / delivery**: <observations on talking-head video>
- **Pacing**: <fast/slow/uneven>
- **Visual style**: <brand audit, ad review, design observations>
- **Audio quality / atmosphere**: <music, silence, background>

Exact extra sections depend on the use case (brand audit, ad review, talk delivery review, client-call read). Use case is inferred from the source + the user's verbal framing when invoking.

Step 9 — Optional: capture to second-brain

After any mode completes, offer:

"Want to capture this to second-brain? I'll write a `call-<slug>.md` (or `meeting-` / `note-` / `resource-`) to `${SECOND_BRAIN_VAULT:-$HOME/Documents/SecondBrain}/raw/` with the summary, source URL, and transcript link."

Type prefix by source:

SourcePrefix
Loom / Zoom / Riverside / Otter / call recordingcall-
Meeting (own notes, not a transcript)meeting-
Talk / keynote / conferencenote-
Ad / landing-page video / marketing reference / competitor videoresource-

File body: 1-line source, the summary, link to full workdir.

Step 10 — Report

In chat:

  • One-line headline: <source> · <title> · <duration> · <mode> · <word count> words
  • Workdir path
  • For visual / multimodal: brief list of top 3 key moments
  • For all modes: any action items / decisions flagged for triage
  • If captured to second-brain: that path too

Sources reference

SourceDownloadBuilt-in transcriptNotes
YouTubeyt-dlpAuto-subs (--write-auto-sub)Same as the prior youtube-transcript skill
Loomyt-dlp (Loom supported)Yes — fetch via embed metadata or Loom APIAsync screenshare focus — prime use case
Vimeoyt-dlpSometimesMarketing/embed videos
RiversideDirect URL from export, or local fileYes — Riverside generates themPodcast episodes
ZoomLocal .mp4 (downloaded recordings)Sometimes (Zoom audio transcript file)Client calls
X / IG / TikTokDefer to social-fetch for metadata, yt-dlp for fileNoShort-form
Local filen/an/aDrop a path

Composes with

  • social-fetch — for X/IG/TikTok URL metadata (engagement, author, replies) before video processing
  • second-brain — capture summary as raw/call-<slug>.md, meeting-, note-, or resource- per source type
  • decide — when a video contains a flagged decision, route to /decide for structured capture
  • pm — action items flagged in summary can be triaged to project boards
  • slide-deck — talk recordings → outline extraction → deck draft (loop)
  • jab-hook — quotes + clip-worthy moments from podcast/talk videos feed BIP/promo posts
  • `skillify from-video` — primary use case for visual mode on process recordings. the user records themselves doing a workflow (Loom/screen-share), this skill extracts transcript + key visual moments, then skillify synthesizes the workflow into a SKILL.md. "Record once, AI converts to skill."

Error handling

FailureResponse
Video unavailable / private / region-lockedReport and stop
No subtitles + Whisper not installedTell the user: pip install mlx-whisper (Apple Silicon) or pip install faster-whisper (anything else)
ffmpeg missing (for visual/multimodal)Tell the user: brew install ffmpeg
Vision pass returns empty / unclearLower the frame count, retry, or fall back to transcript-only with a note
Multimodal requested but no $GEMINI_API_KEY and >30min videoWarn cost, offer to fall back to visual mode
yt-dlp binary missingbrew install yt-dlp

Notes on quality

  • User picks depth, not the skill. Transcript / visual / multimodal are 3 different cost + latency profiles. Long videos (>10 min) always confirm before spending on visual/multimodal.
  • Platform transcript first, Whisper second. YouTube auto-subs, Loom transcripts, Riverside built-in transcripts — all free + instant when they exist. Fall back to local Whisper only when nothing platform-provided works.
  • Local Whisper is the fast path. MLX on M-series Macs transcribes faster than real-time; faster-whisper is the equivalent elsewhere. Cloud Whisper is a distant second choice — costs money, network dependency, worse latency on typical durations.
  • Frame cadence by source type. Screen-share / demos need 1 frame per 5s (UI changes fast); talking-head podcasts need 1 per 30s (slow change). Default 15s if unsure. Wrong cadence = missed key moments OR wasted vision-pass cost.
  • 720p is plenty. Downloading 1080p / 4K for transcription + frame analysis wastes bandwidth + storage. yt-dlp -f "bv*[height<=720]+ba/b[height<=720]" is the default.
  • Scene-change detection catches slide transitions. When the video is a slide presentation, add ffmpeg -vf "select='gt(scene,0.3)'" to force a frame on each detected slide change — more reliable than pure time-based sampling.
  • Multimodal cost warning is non-optional. Gemini multimodal on a 60-min video is meaningfully expensive. Warn before running; offer transcript-only as fallback if the user isn't sure.
  • Summary format includes routing hints. ## Decisions flagged + ## Action items flagged sections signal /decide and /pm follow-ups. Downstream composability lives in the summary structure.

관련 작업

같은 저장소의 Skills

더 많은 Skills

모든 Skills