Claude Skill

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. Three depth modes user picks per invocation — transcript (just words, fast/free), visual (transcript + ffmpeg frame extraction + Claud

LLM Mart · 0 points · 6 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download coreyhaines31-makerskills-skills_watch-video-1868b81.zip · 6 KB
Part of coreyhaines31/makerskills — 18 skills

Install

skills CLI npx skills add https://github.com/coreyhaines31/makerskills/tree/main/skills/watch-video
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install coreyhaines31-makerskills@llmmart
Git git clone https://github.com/coreyhaines31/makerskills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole coreyhaines31/makerskills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

/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

Invocation Mode What you get
/watch-video <url> transcript (default) Clean text, metadata, optional chapters
/watch-video <url> transcript transcript Same as default
/watch-video <url> visual visual Transcript + frames at intervals + Claude vision pass identifying key moments
/watch-video <url> multimodal multimodal Native 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:

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:

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.
  2. MLX-Whisper local (default fallback — fast on Mac M-series):

    # 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>

  3. whisper.cpp (further fallback if MLX unavailable)

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

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):

# 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 type Frame cadence
Screen-share / Loom / demo 1 frame per 5s (UI changes fast)
Talking head / podcast 1 frame per 30s (slow change)
Slide presentation 1 frame per 10s + force a frame on each detected scene change
Default if unsure 1 frame per 15s
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):

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:

# 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:

# 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.

    # 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.

  2. 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:

## 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:

Source Prefix
Loom / Zoom / Riverside / Otter / call recording call-
Meeting (own notes, not a transcript) meeting-
Talk / keynote / conference note-
Ad / landing-page video / marketing reference / competitor video resource-

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

Source Download Built-in transcript Notes
YouTube yt-dlp Auto-subs (--write-auto-sub) Same as the prior youtube-transcript skill
Loom yt-dlp (Loom supported) Yes — fetch via embed metadata or Loom API Async screenshare focus — prime use case
Vimeo yt-dlp Sometimes Marketing/embed videos
Riverside Direct URL from export, or local file Yes — Riverside generates them Podcast episodes
Zoom Local .mp4 (downloaded recordings) Sometimes (Zoom audio transcript file) Client calls
X / IG / TikTok Defer to social-fetch for metadata, yt-dlp for file No Short-form
Local file n/a n/a Drop 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

Failure Response
Video unavailable / private / region-locked Report and stop
No subtitles + Whisper not installed Tell the user: pip install mlx-whisper (Mac)
ffmpeg missing (for visual/multimodal) Tell the user: brew install ffmpeg
Vision pass returns empty / unclear Lower the frame count, retry, or fall back to transcript-only with a note
Multimodal requested but no $GEMINI_API_KEY and >30min video Warn cost, offer to fall back to visual mode
yt-dlp binary missing brew 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 MLX-Whisper local only when nothing platform-provided works.
  • MLX-Whisper local is the fast path on Mac. M-series machines transcribe faster than real-time. 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.
Files (makerskills)
  • SKILL.md 14.5 KB
    ---
    name: watch-video
    description: When you want to extract content from a video — YouTube, Loom, Vimeo, Riverside, Zoom recording, local MP4, X/IG video, anything yt-dlp supports. Three depth modes user picks per invocation — transcript (just words, fast/free), visual (transcript + ffmpeg frame extraction + Claude vision pass on key moments), multimodal (Gemini native video ingestion if $GEMINI_API_KEY set, else dense Claude vision). Uses MLX-Whisper local on Mac for transcription, falls back to platform-provided transcripts when available (Loom, Riverside, YouTube auto-subs). Saves to ~/Documents/videos/<source>-<slug>-<date>/ and optionally captures summary to second-brain raw/ as call-/meeting-/note-. Triggers on "/watch-video <url>," "watch this video," "transcribe this loom," "analyze this video," "summarize this recording," "key moments from this," "what happened in this video." This skill replaces and broadens the prior youtube-transcript skill.
    metadata:
      version: 0.2.2
    ---
    
    # /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
    
    | Invocation | Mode | What you get |
    |---|---|---|
    | `/watch-video <url>` | **transcript** (default) | Clean text, metadata, optional chapters |
    | `/watch-video <url> transcript` | transcript | Same as default |
    | `/watch-video <url> visual` | visual | Transcript + frames at intervals + Claude vision pass identifying key moments |
    | `/watch-video <url> multimodal` | multimodal | Native 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.
    
    2. **MLX-Whisper local** (default fallback — fast on Mac M-series):
       ```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>`
    
    3. **whisper.cpp** (further fallback if MLX unavailable)
    
    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 type | Frame cadence |
    |---|---|
    | Screen-share / Loom / demo | 1 frame per **5s** (UI changes fast) |
    | Talking head / podcast | 1 frame per **30s** (slow change) |
    | Slide presentation | 1 frame per **10s** + force a frame on each detected scene change |
    | Default if unsure | 1 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.
    
    2. **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:
    
    | Source | Prefix |
    |---|---|
    | Loom / Zoom / Riverside / Otter / call recording | `call-` |
    | Meeting (own notes, not a transcript) | `meeting-` |
    | Talk / keynote / conference | `note-` |
    | Ad / landing-page video / marketing reference / competitor video | `resource-` |
    
    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
    
    | Source | Download | Built-in transcript | Notes |
    |---|---|---|---|
    | YouTube | `yt-dlp` | Auto-subs (`--write-auto-sub`) | Same as the prior youtube-transcript skill |
    | Loom | `yt-dlp` (Loom supported) | Yes — fetch via embed metadata or Loom API | Async screenshare focus — prime use case |
    | Vimeo | `yt-dlp` | Sometimes | Marketing/embed videos |
    | Riverside | Direct URL from export, or local file | Yes — Riverside generates them | Podcast episodes |
    | Zoom | Local `.mp4` (downloaded recordings) | Sometimes (Zoom audio transcript file) | Client calls |
    | X / IG / TikTok | Defer to `social-fetch` for metadata, yt-dlp for file | No | Short-form |
    | Local file | n/a | n/a | Drop 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
    
    | Failure | Response |
    |---|---|
    | Video unavailable / private / region-locked | Report and stop |
    | No subtitles + Whisper not installed | Tell the user: `pip install mlx-whisper` (Mac) |
    | ffmpeg missing (for visual/multimodal) | Tell the user: `brew install ffmpeg` |
    | Vision pass returns empty / unclear | Lower the frame count, retry, or fall back to transcript-only with a note |
    | Multimodal requested but no `$GEMINI_API_KEY` and >30min video | Warn cost, offer to fall back to visual mode |
    | `yt-dlp` binary missing | `brew 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 MLX-Whisper local only when nothing platform-provided works.
    - **MLX-Whisper local is the fast path on Mac.** M-series machines transcribe faster than real-time. 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.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related