Video Transcription & Analysis

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

by coreyhaines31 · MIT license · ★ 855 on GitHub

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

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…

---
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 local Whisper for transcription (MLX-Whisper on Apple Silicon, faster-whisper elsewhere), 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.3
---

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

Overview

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

Example prompts

/watch-video — Transcribe and analyze any video at the depth you choose
Manual install (npx, ZIP)
Claude Codenpx skills add coreyhaines31/makerskills --skill watch-video -g -a claude-code
Claude Code (degit)npx degit coreyhaines31/makerskills/skills/watch-video#main ~/.claude/skills/watch-video
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md14.8 KB
Read SKILL.md here
coreyhaines31/main1 file shown
SKILL.md
Show the full text322 lines

/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 on Apple Silicon Macs):

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

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 (Apple Silicon) or pip install faster-whisper (anything else)
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 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.
1---
2name: watch-video
3description: 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 local Whisper for transcription (MLX-Whisper on Apple Silicon, faster-whisper elsewhere), 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.
4metadata:
5 version: 0.2.3
6---
7 
8# /watch-video — Transcribe and analyze any video at the depth you choose
9 
10Replaces and broadens the prior `youtube-transcript` skill. YouTube is now one of many sources; depth is user-controlled.
11 
12## Step 1 — Parse input
13 
14Accept:
15- **YouTube**: full URL, `youtu.be/<id>`, `youtube.com/shorts/<id>`, raw 11-char ID
16- **Loom**: `loom.com/share/<id>` or `loom.com/embed/<id>`
17- **Vimeo**: `vimeo.com/<id>`
18- **Riverside**: download URL or local file
19- **Zoom**: local `.mp4` from a downloaded recording
20- **X / IG / TikTok video**: URL — defers to `social-fetch` for metadata, uses yt-dlp for the file
21- **Local file**: any path to an `.mp4` / `.mov` / `.webm` / `.mkv`
22 
23Detect source from URL pattern or file extension. If ambiguous, ask.
24 
25## Step 2 — Parse depth mode
26 
27| Invocation | Mode | What you get |
28|---|---|---|
29| `/watch-video <url>` | **transcript** (default) | Clean text, metadata, optional chapters |
30| `/watch-video <url> transcript` | transcript | Same as default |
31| `/watch-video <url> visual` | visual | Transcript + frames at intervals + Claude vision pass identifying key moments |
32| `/watch-video <url> multimodal` | multimodal | Native video to Gemini (if `$GEMINI_API_KEY`), else dense Claude vision frame-by-frame |
33 
34If the depth isn't specified and the video is >10 minutes, ask before defaulting (visual/multimodal cost real money on long videos).
35 
36## Step 3 — Pull metadata
37 
38For URL sources, use yt-dlp:
39 
40```bash
41yt-dlp --print "%(title)s|%(uploader)s|%(duration_string)s|%(upload_date>%Y-%m-%d)s|%(description)s" \
42 --print "%(chapters)j" --skip-download "<url>"
43```
44 
45Capture: title, uploader/channel, duration, upload date, description (first paragraph), chapters (JSON or null).
46 
47For local files, use ffprobe:
48 
49```bash
50ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "<file>"
51```
52 
53## Step 4 — Build workdir
54 
55```
56~/Documents/videos/<source>-<slug>-<date>/
57```
58 
59Where:
60- `source`: `youtube` / `loom` / `vimeo` / `riverside` / `zoom` / `local`
61- `slug`: kebab-case of title (first 4–6 words, max 50 chars)
62- `date`: `YYYY-MM-DD`
63 
64## Step 5 — Get the transcript
65 
66**Backend selection** (in order):
67 
681. **Platform-provided transcript** if it exists and looks complete:
69 - YouTube: `yt-dlp --write-sub --write-auto-sub --skip-download --sub-lang en --sub-format vtt`
70 - Loom: fetch via `https://www.loom.com/share/<id>` page metadata or Loom API if `$LOOM_API_KEY` set
71 - Riverside: built-in transcripts available on the recording's share page
72 - If platform transcript exists and has timestamps, use it. Skip Whisper.
73 
742. **MLX-Whisper local** (default on Apple Silicon Macs):
75 ```bash
76 # Install once: pip install mlx-whisper
77 python3 -c "import mlx_whisper; mlx_whisper.transcribe('<file>', path_or_hf_repo='mlx-community/whisper-large-v3-turbo')" \
78 > "<workdir>/transcript-raw.json"
79 ```
80 Or via the CLI: `mlx_whisper <file> --model mlx-community/whisper-large-v3-turbo --output-dir <workdir>`
81 
823. **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.
83 
84Download the video file first if it's a URL (use yt-dlp; Loom/Vimeo/YT all supported):
85 
86```bash
87yt-dlp -f "bv*[height<=720]+ba/b[height<=720]" -o "<workdir>/video.%(ext)s" "<url>"
88```
89 
90720p is plenty for transcription and frame analysis (smaller download, faster processing).
91 
92**Clean the transcript** (only needed for YouTube auto-subs which have rolling captions; Whisper output is already clean):
93 
94```bash
95# YouTube VTT cleanup — de-dup rolling captions, strip tags, paragraph-break on cue gaps >2s
96awk '
97 /^WEBVTT/ || /^Kind:/ || /^Language:/ || /^NOTE/ { next }
98 /-->/ { in_cue = 1; last = ""; next }
99 /^$/ { if (last) print last; in_cue = 0; last = ""; next }
100 in_cue { gsub(/<[^>]+>/, "", $0); last = $0 }
101 END { if (last) print last }
102' "<workdir>/transcript.en.vtt" | awk '!seen[$0]++' > "<workdir>/transcript.txt"
103```
104 
105Save final to `<workdir>/transcript.txt`.
106 
107## Step 6 — If `transcript` mode: stop here
108 
109Output:
110- `transcript.txt`
111- `metadata.json`
112- One-line summary in chat: title, source, duration, word count
113- Path to workdir
114- (Optional) Step 9 — offer to capture to second-brain
115 
116## Step 7 — If `visual` mode: extract frames + vision pass
117 
118### Frame extraction (ffmpeg)
119 
120Cadence by source heuristic:
121 
122| Source type | Frame cadence |
123|---|---|
124| Screen-share / Loom / demo | 1 frame per **5s** (UI changes fast) |
125| Talking head / podcast | 1 frame per **30s** (slow change) |
126| Slide presentation | 1 frame per **10s** + force a frame on each detected scene change |
127| Default if unsure | 1 frame per **15s** |
128 
129```bash
130mkdir -p "<workdir>/frames"
131ffmpeg -i "<workdir>/video.mp4" -vf "fps=1/15" "<workdir>/frames/frame-%04d.png" -y
132```
133 
134For scene-change detection (slide decks especially):
135 
136```bash
137ffmpeg -i "<workdir>/video.mp4" -vf "select='gt(scene,0.3)',showinfo" -vsync vfr "<workdir>/frames/scene-%04d.png" 2> "<workdir>/scene-detection.log"
138```
139 
140### Vision pass
141 
142Pair each frame with the transcript chunk for the same timestamp window. Then batch-send to Claude vision for synthesis.
143 
144**Per-frame batch prompt** (up to ~10 frames per call):
145 
146> 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.
147 
148Save the output as `<workdir>/moments.md`:
149 
150```markdown
151# Key moments — <title>
152 
153## 00:00:15 (frame-001.png)
154**On screen**: Login form, email field focused
155**Transcript**: "So you just open it up and..."
156**Note**: Beginning of UI demo
157 
158## 00:00:45 (frame-002.png)
159**On screen**: Dashboard with 4 cards
160**Transcript**: "And here's where you see all your projects."
161**Note**: Major view change — first time the dashboard appears
162```
163 
164### Generate summary
165 
166After moments are identified, synthesize the whole video into `<workdir>/summary.md`:
167 
168```markdown
169# Summary — <title>
170 
171**Source:** <source URL / file>
172**Duration:** <hh:mm:ss>
173**Watched at:** <date>
174**Mode:** visual
175 
176## TL;DR
177<2–4 sentences>
178 
179## Key moments
180- 00:00:15 — <one-line>
181- 00:00:45 — <one-line>
182 
183## Action items flagged
184- <item> [timestamp]
185 
186## Decisions flagged
187- <decision> [timestamp] — consider routing to /decide
188 
189## Quotes worth keeping
190- "..." [timestamp]
191 
192## Open questions
193- <question raised but not answered>
194```
195 
196## Step 8 — If `multimodal` mode
197 
198### Backend selection
199 
2001. **Gemini native** if `$GEMINI_API_KEY` is set (much cheaper + faster than per-frame for long videos):
201 
202 **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.
203 
204 ```bash
205 # Step 1: Upload video via Files API
206 FILE_URI=$(curl -s -X POST "https://generativelanguage.googleapis.com/upload/v1beta/files?key=$GEMINI_API_KEY" \
207 -H "X-Goog-Upload-Command: start, upload, finalize" \
208 -H "Content-Type: video/mp4" \
209 --data-binary "@<workdir>/video.mp4" | jq -r '.file.uri')
210 
211 # Wait until file is ACTIVE (Gemini processes the video first)
212 while true; do
213 STATE=$(curl -s "$FILE_URI?key=$GEMINI_API_KEY" | jq -r '.state')
214 [ "$STATE" = "ACTIVE" ] && break
215 sleep 3
216 done
217 
218 # Step 2: Generate content with the file + multimodal-analysis prompt
219 curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key=$GEMINI_API_KEY" \
220 -H "Content-Type: application/json" \
221 -d "{
222 \"contents\":[{
223 \"parts\":[
224 {\"file_data\":{\"mime_type\":\"video/mp4\",\"file_uri\":\"$FILE_URI\"}},
225 {\"text\":\"<multimodal analysis prompt — see Step 7's summary template + use-case extensions>\"}
226 ]
227 }]
228 }"
229 ```
230 
231 Files persist in Gemini Files API for ~48 hours — useful for re-querying the same video with different prompts.
232 
2332. **Dense Claude vision fallback** if no Gemini key:
234 - Frame cadence: 1 frame per **3s** (much denser than visual mode)
235 - Batch through Claude vision with the multimodal-analysis prompt
236 - Slower and more expensive than Gemini for long videos — warn the user before running on >10min content
237 
238### Multimodal output
239 
240Same `summary.md` template as Step 7 + an extended section:
241 
242```markdown
243## Multimodal observations
244- **Body language / delivery**: <observations on talking-head video>
245- **Pacing**: <fast/slow/uneven>
246- **Visual style**: <brand audit, ad review, design observations>
247- **Audio quality / atmosphere**: <music, silence, background>
248```
249 
250Exact 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.
251 
252## Step 9 — Optional: capture to second-brain
253 
254After any mode completes, offer:
255 
256> *"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."*
257 
258Type prefix by source:
259 
260| Source | Prefix |
261|---|---|
262| Loom / Zoom / Riverside / Otter / call recording | `call-` |
263| Meeting (own notes, not a transcript) | `meeting-` |
264| Talk / keynote / conference | `note-` |
265| Ad / landing-page video / marketing reference / competitor video | `resource-` |
266 
267File body: 1-line source, the summary, link to full workdir.
268 
269## Step 10 — Report
270 
271In chat:
272 
273- One-line headline: `<source> · <title> · <duration> · <mode> · <word count> words`
274- Workdir path
275- For `visual` / `multimodal`: brief list of top 3 key moments
276- For all modes: any action items / decisions flagged for triage
277- If captured to second-brain: that path too
278 
279## Sources reference
280 
281| Source | Download | Built-in transcript | Notes |
282|---|---|---|---|
283| YouTube | `yt-dlp` | Auto-subs (`--write-auto-sub`) | Same as the prior youtube-transcript skill |
284| Loom | `yt-dlp` (Loom supported) | Yes — fetch via embed metadata or Loom API | Async screenshare focus — prime use case |
285| Vimeo | `yt-dlp` | Sometimes | Marketing/embed videos |
286| Riverside | Direct URL from export, or local file | Yes — Riverside generates them | Podcast episodes |
287| Zoom | Local `.mp4` (downloaded recordings) | Sometimes (Zoom audio transcript file) | Client calls |
288| X / IG / TikTok | Defer to `social-fetch` for metadata, yt-dlp for file | No | Short-form |
289| Local file | n/a | n/a | Drop a path |
290 
291## Composes with
292 
293- `social-fetch` — for X/IG/TikTok URL metadata (engagement, author, replies) before video processing
294- `second-brain` — capture summary as `raw/call-<slug>.md`, `meeting-`, `note-`, or `resource-` per source type
295- `decide` — when a video contains a flagged decision, route to `/decide` for structured capture
296- `pm` — action items flagged in summary can be triaged to project boards
297- `slide-deck` — talk recordings → outline extraction → deck draft (loop)
298- `jab-hook` — quotes + clip-worthy moments from podcast/talk videos feed BIP/promo posts
299- **`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."
300 
301## Error handling
302 
303| Failure | Response |
304|---|---|
305| Video unavailable / private / region-locked | Report and stop |
306| No subtitles + Whisper not installed | Tell the user: `pip install mlx-whisper` (Apple Silicon) or `pip install faster-whisper` (anything else) |
307| ffmpeg missing (for visual/multimodal) | Tell the user: `brew install ffmpeg` |
308| Vision pass returns empty / unclear | Lower the frame count, retry, or fall back to transcript-only with a note |
309| Multimodal requested but no `$GEMINI_API_KEY` and >30min video | Warn cost, offer to fall back to visual mode |
310| `yt-dlp` binary missing | `brew install yt-dlp` |
311 
312## Notes on quality
313 
314- **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.
315- **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.
316- **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.
317- **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.
318- **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.
319- **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.
320- **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.
321- **Summary format includes routing hints.** `## Decisions flagged` + `## Action items flagged` sections signal `/decide` and `/pm` follow-ups. Downstream composability lives in the summary structure.
322 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 855
Checked
Source
coreyhaines31/makerskills ↗
Creator
coreyhaines31 · 62 listings
View creator

Similar skills

See all →

More from coreyhaines31

SkillLead Magnet Buildercoreyhaines31/marketingskills · by coreyhaines31Tell us about your business and who you sell to, and get back a ready-to-launch free offer that turns website visitors into email signups and future customers.★ 51.1k GitHub starsSkillGrowth Experimentation Programcoreyhaines31/marketingskills · by coreyhaines31When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program," or "experiment playbook." Use this whenever someone is comparing two approaches and wants to measure which performs better, or when they want to build a systematic experimentation practice. For tracking implementation, see analytics. For page-level conversion optimization, see cro.★ 51.1k GitHub starsSkillAd Creative Generatorcoreyhaines31/marketingskills · by coreyhaines31When the user wants to generate, iterate, or scale ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform. Also use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' 'write me some ads,' 'Facebook ad copy,' 'Google ad headlines,' 'LinkedIn ad text,' 'static ads,' 'ad templates,' 'iMessage ad,' 'chat reveal ad,' 'ChatGPT ad,' 'Apple Notes ad,' 'AirDrop ad,' 'creative strategy,' 'creative roadmap,' 'creative retro,' 'hook writing,' 'creative review page,' 'present ad creative for approval,' 'motion video ad,' 'faceless video ad,' 'UGC ad,' 'greenscreen ad,' 'TikTok/Reels ad format,' 'which ad format to make,' 'Meta ad format tier list,' or 'creative format taxonomy.' Use this whenever someone needs to produce ad copy at scale or iterate on existing ads. For campaign strategy and targeting, see ads. For landing page copy, see copywriting.★ 51.1k GitHub starsSkillBusiness Idea Pressure Testcoreyhaines31/makerskills · by coreyhaines31When you want to pressure-test a potential new business, product, or side project against the serial-founder filter. Not "marketing ideas for a product" (that's marketing-skills:marketing-ideas) — this is "should this business exist + can you win it." Runs the idea through a structured framework (problem, audience, wedge, monetization, moat, portfolio fit, distribution, energy fit, opportunity cost), checks domain availability via /domain, optionally triggers /deep-research for market validation, and outputs a viability brief: build / sleep on it / pass. Archives every idea to ~/.config/makerskills/business-brainstorm/archive/ so past work is searchable. Triggers on "/business-brainstorm," "/brainstorm," "new business idea," "should I build X," "pressure test this idea," "validate this idea," "is X a good business," "what about a [type] for [audience]."★ 855 GitHub starsSkillTeam Knowledge Basecoreyhaines31/makerskills · by coreyhaines31Your team's shared, AI-ready knowledge base — people, companies, meetings, SOPs, and decisions structured so an agent can answer on your team's behalf. Team-scope sibling to second-brain. Modes — capture, compile (wiki pages + INDEX.md), query (trust-weighted, saved to outputs/), review (verify / deprecate / supersede stale captures), lint, connect, search. Structured raw dirs (people/, companies/, meetings/, sops/, decisions/, customer-language/, sales-objections/). Every capture stamps author, timestamp, and trust status. Optional sync from call transcripts, Slack/email exports, CRM. Vault at ${COMPANY_BRAIN_VAULT:-$HOME/Documents/CompanyBrain}/. Triggers on "/company-brain," "/cb," "capture this into the team brain," "log this meeting," "save this SOP," "compile the company wiki," "query the team brain," "what does the team know about X," "review the company brain," "lint the company brain," "who's the internal expert on X.★ 855 GitHub starsSkillMonthly Company CFOcoreyhaines31/makerskills · by coreyhaines31Monthly CFO workflow for a company or agency — pull raw data from bank + payment processor + payroll + expense management, categorize and reconcile, compute end-of-month cash via transaction-sum method, update a scenario projector for forward forecasting, write the monthly snapshot report, surface decisions to leadership. Modes — monthly (default; the standing report), weekly (thin cash pulse), scenario (ad-hoc modeling in the projector), pickup (resume where the prior run left off). Anonymized team-scope sibling to personal-cfo (which handles personal household finances). Composes with company-brain (report gets stored + wiki-indexed there), toolify (wire company-specific data sources), loopify (schedule the monthly + weekly runs). Triggers on "/company-cfo," "/cfo," "monthly cash report," "do the CFO snapshot," "CFO monthly," "let's run CFO," "cash projection," "runway forecast," "monthly financials," "cash pulse.★ 855 GitHub stars