From frames
Extract frames from a video file or screen recording (.mov, .mp4, .webm, .avi, .mkv) so Claude can view, review, or analyze it. Do NOT use for GIF conversion (use /gif instead).
npx claudepluginhub ramonclaudio/skills --plugin framesThis skill is limited to using the following tools:
ultrathink
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Performs token-optimized structural code search using tree-sitter AST parsing to discover symbols, outline files, and unfold code without reading full files.
ultrathink
Claude cannot view video files directly but can view images. Extract frames using ffmpeg, then read a sample. Claude supports up to 600 images per request with the 1M context window, so sampling can be generous.
which ffmpeg 2>/dev/null && ffmpeg -version 2>&1 | head -1 || echo "NOT INSTALLED - run: brew install ffmpeg"If ffmpeg is NOT INSTALLED, stop immediately and tell the user to install it. Do not attempt any extraction.
Parse the video path from $ARGUMENTS.
File paths with spaces and special characters break quoting. Copy to a clean /tmp path using glob on a unique substring (timestamp, keyword).
/bin/cp -f /path/to/dir/*UNIQUE_PART* /tmp/video.mov && \
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of csv=p=0 /tmp/video.mov
Example for Screen Recording 2026-01-10 at 11.33.27 AM.mov:
/bin/cp -f ~/Desktop/Screen*11.33.27* /tmp/video.mov && \
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of csv=p=0 /tmp/video.mov
Select FPS based on duration from the probe output. Scale to 640px width to save context tokens.
| Duration | FPS | Rationale |
|---|---|---|
| <5s | native | Short clip, need full detail |
| 5-30s | 2 | 10-60 frames |
| 30s-2min | 1 | 30-120 frames |
| >2min | 0.5 | Keep frame count manageable |
trash /tmp/video-frames 2>/dev/null; mkdir -p /tmp/video-frames && \
ffmpeg -y -v warning -i /tmp/video.mov -vf "fps=FPS,scale=640:-1" /tmp/video-frames/frame_%04d.png && \
/bin/ls /tmp/video-frames/ | wc -l
For short videos (<5s), omit the fps= filter but keep the scale:
ffmpeg -y -v warning -i /tmp/video.mov -vf "scale=640:-1" /tmp/video-frames/frame_%04d.png
To extract a specific time range, add -ss START -t DURATION before -i:
ffmpeg -y -v warning -ss 00:01:00 -t 10 -i /tmp/video.mov -vf "fps=2,scale=640:-1" /tmp/video-frames/frame_%04d.png
List frames, then read a sample evenly distributed across the video. Use parallel Read calls for speed.
/bin/ls /tmp/video-frames/
| Frame count | Frames to read |
|---|---|
| <30 | All |
| 30-100 | 15-20 evenly spaced |
| 100-300 | 30-40 evenly spaced |
| >300 | 50-60 evenly distributed |
Pick frame numbers evenly spaced across the total. Read them with the Read tool, multiple per response.
| Problem | Solution |
|---|---|
| Spaces in filenames | /bin/cp -f with glob handles any filename |
| Quoted paths fail | Glob avoids quoting issues |
cd fails (zoxide) | Never use cd, use absolute paths |
| Shell aliases interfere | Use /bin/cp, /bin/ls for reliability |
scale=640:-1 fails on videos with odd-height dimensions. Use scale=640:-2 if ffmpeg errors with "height not divisible by 2".color_transfer=smpte2084 in probe output and tone-map to SDR first with avconvert./tmp disk. Always check duration before extracting and pick a conservative FPS..webm or piped streams), the FPS table breaks. Fall back to 1 FPS and count frames after extraction./bin/cp -f *UNIQUE*) matches multiple files if the substring isn't unique. Verify only one file matches before proceeding.