Watch video
Skill Terminusapp-ai/watch-video/plugins/watch-video/skills/watch-video
This skill should be used when the user provides a path to a video file (.mp4, .mov, .webm, .mkv, .avi) and asks Claude to watch, describe, summarize, debug, verify, or analyze its contents. Common cases include screen-recordings of bug reproductions, mobile app demos, tutorials, UI walkthroughs, and short clips. The skill extracts JPEG frames with ffmpeg and instructs Claude to read them through the native Read tool. It auto-handles filenames containing spaces, colons, or other special characters that break ad-hoc ffmpeg commands. Requires ffmpeg on PATH.From its SKILL.md
npx -y skills add Terminusapp-ai/watch-video --skill watch-videoAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.3 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
Watch Video
Purpose
Convert a video file into a sequence of JPEG frames so Claude can analyze its visual content through the native Read image tool. Claude cannot read video files directly, but it can read images — this skill bridges the gap.
When to invoke
Invoke when any of these match:
- The user shares a path to a
.mp4,.mov,.webm,.mkv,.avi, or similar file and asks Claude to look at it, watch it, describe it, summarize it, verify a fix in it, or check what happens in it. - The user shares a screen recording demonstrating a bug.
- The user asks "what is shown in this video" or "did the app behave correctly in this recording".
- A previous step recorded a Playwright/Maestro/Detox test run and the user wants Claude to inspect the result.
Do NOT invoke for: live streams, audio-only files, GIFs (use Read directly), or videos already provided as still frames.
Prerequisites
ffmpeg and ffprobe must be available on PATH:
brew install ffmpeg # macOS
sudo apt-get install ffmpeg # Debian/Ubuntu
The script verifies this and emits a clear error if missing.
Workflow
- Run
scripts/extract_frames.sh <video_path>— pass the path verbatim, including spaces and special characters. The script copies the file to a safe temp path internally. - Parse the JSON output for
output_dir,frames[],frame_count,video_duration_seconds, andstrategy. - If
frame_countis large (>30), sanity-check that a smaller frame set isn't sufficient before reading them all — eachReadof a JPG consumes vision tokens. - Read each path in
frames[]with theReadtool. The frames are timestamp-ordered:frame_001.jpgis earliest, the highest-numbered frame is latest. - Analyze the frames to answer the user's question. When relevant, reference frames by their timestamp (compute as
index * (1 / effective_fps)for fps mode, or use the visible content for scene-detection mode). - Optionally clean up:
rm -rf "$OUTPUT_DIR"after the analysis is complete and reported.
Default behavior (auto strategy)
With no flags, the script picks an adaptive frame rate based on duration so the total stays in a useful range (~8–25 frames):
| Video duration | Default fps | Approx frames |
|---|---|---|
| ≤ 10s | 1.0 | up to 10 |
| ≤ 30s | 0.5 | up to 15 |
| ≤ 60s | 0.333 | up to 20 |
| ≤ 2 min | 0.2 | up to 24 |
| ≤ 5 min | 0.125 | up to ~37 |
| > 5 min | 0.0667 | depends |
Frames are downscaled to 590px wide by default — readable at mobile-screenshot scale without flooding the context window.
Useful flags
| Flag | Purpose | Example |
|---|---|---|
--max-frames N | Cap total frames to N (auto-calculates fps) | --max-frames 20 |
--fps F | Force a specific frame rate | --fps 1 |
--scene-threshold T | Extract one frame per detected scene change. T in 0.0–1.0; lower = more sensitive | --scene-threshold 0.3 |
--width W | Output width in pixels (height auto-scaled) | --width 800 |
--quality Q | JPEG quality 1 (best) – 31 (worst), default 4 | --quality 2 |
--output-dir D | Custom output directory (default: mktemp -d) | --output-dir /tmp/myframes |
Common usage patterns
Bug-reproduction screen recording (short, mobile)
scripts/extract_frames.sh "/path/to/ScreenRecording.mp4"
Auto-mode handles it. Read all frames; describe what changes between them.
Long tutorial — pick scene transitions only
scripts/extract_frames.sh tutorial.mp4 --scene-threshold 0.3
Returns one frame per visual scene change (e.g., slide transitions). Best for presentations, edited footage.
Read text on UI screens (OCR-style)
scripts/extract_frames.sh screencast.mp4 --width 1180 --quality 1 --max-frames 25
Higher resolution + best JPEG quality so small UI text remains legible.
Strict frame budget
scripts/extract_frames.sh long.mp4 --max-frames 12
The script computes an fps that yields ~12 evenly-spaced frames regardless of duration.
Output format
The script prints a single JSON object on stdout. Example:
{
"output_dir": "/tmp/watch-video-frames.AbC123",
"video_duration_seconds": 19.67,
"strategy": "auto",
"effective_fps": 0.5,
"frame_width": 590,
"frame_height": 1278,
"frame_count": 10,
"frames": [
"/tmp/watch-video-frames.AbC123/frame_001.jpg",
"/tmp/watch-video-frames.AbC123/frame_002.jpg"
]
}
On failure, a JSON object with an "error" key prints to stderr and the process exits with code 1.
Troubleshooting
- "ffmpeg not found" — install ffmpeg and re-run.
- "could not read video duration" — the file is corrupt, truncated, or uses a codec ffmpeg can't decode. Try
ffprobe <file>directly to see ffmpeg's diagnostics. - "no frames extracted" — the filter selected zero frames. With
--scene-threshold, the threshold is too high; lower it (try 0.2). Otherwise the video may be very short — pass--fps 2to force extraction. - Frames look blurry / small UI text unreadable — increase
--width(try 1180 for iPhone-portrait recordings) and lower--quality(try 1 or 2). - Too many frames blow context — pass
--max-frames 15to cap. - Filename has spaces / colons / quotes — pass it verbatim; the script normalizes the path internally. Do not pre-escape.
- "video file not found" but the file is clearly there — the path string may not be byte-identical to the filename. iOS screen recordings notoriously contain a Unicode narrow no-break space (U+202F, bytes
e2 80 af) between the time and "AM"/"PM" — it looks like a regular space but isn't. Get the path with shell completion orfind -print0 | xargs -0rather than typing it; that preserves the exact bytes.
What ships with it: 1 file
5.3 KB alongside SKILL.md, 1 of them executable
scripts/
- extract_frames.shruns5.3 KB
Gives 0 of the 12 instructions most video audio skills give in ~1.5k tokens
Counted across 622 of the 795 authors here whose files we hold, read 2026-08-07
- Read individual rule files for detailed explanationsin 21 of 622, across 10 files
- Render final videoin 13 of 622, across 6 files
- Use WAV PCM 16kHz mono audio formatin 12 of 622, across 3 files
- Use this skill when dealing with Remotion codein 11 of 622, across 4 files
- Save generated audio to a WAV filein 11 of 622, across 4 files
- Handle conversion errors gracefullyin 10 of 622, across 6 files
- Add captions to videos alwaysin 10 of 622, across 4 files
- Generate music from text descriptions using MusicGenin 9 of 622, across 2 files
- Do not skip pipeline layersin 9 of 622, across 3 files
- Do not make one tool do everythingin 9 of 622, across 3 files
- Use Azure Document Intelligence for complex PDFsin 9 of 622, across 4 files
- Never ask the user to paste their full API keyin 9 of 622, across 3 files
Said here and by no other author read
- parse JSON output for frame data
- verify frame count is sufficient
- analyze frames to answer the user
- reference frames by timestamp
- clean up the output directory
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.