Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Install and use crv (claude-real-video) — a tool that lets any AI agent watch videos by extracting scene-aware keyframes, deduplicating them, and transcribing audio. Use when the user shares a video URL or file and wants it analyzed, summarized, or discussed.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 80% | 0% |
| case-10 | ✗→✓ | ▲ Improved | -17% | 0% |
crv (claude-real-video) is a CLI tool that extracts meaningful frames and transcripts from videos so AI agents can "see" and "read" them. It uses scene-change detection (not fixed-interval sampling), sliding-window deduplication, and optional Whisper transcription.
Key advantage: Same 58-second clip at fixed 1fps = 58 frames. crv keeps the 26 that actually differ, and --grid packs them into 3 contact sheets. Fewer tokens, nothing missed.
bash# macOS brew install ffmpeg # Linux sudo apt install ffmpeg # Windows winget install Gyan.FFmpeg
bash# Recommended: with audio transcription support pip install "claude-real-video[whisper]" # Core only (frames + dedup) pip install claude-real-video
The [whisper] extra never installs itself — without it there is no speech-to-text (videos that ship their own subtitles still get a transcript).
bashcrv --help ffmpeg -version
Run the bundled installer to symlink this skill into all detected agent platforms:
bashbash install-skill.sh
Or manually copy to your agent's skill directory:
bash# Claude Code cp -r skills/claude-real-video-for-agents ~/.claude/skills/ # Codex cp -r skills/claude-real-video-for-agents ~/.codex/skills/ # OpenCode cp -r skills/claude-real-video-for-agents ~/.opencode/skills/ # Gemini CLI cp -r skills/claude-real-video-for-agents ~/.gemini/skills/
bashcrv "https://www.youtube.com/watch?v=VIDEO_ID"
Output in crv-out/:
frames/ — deduplicated keyframestranscript.txt — plain-text transcriptMANIFEST.txt — summary for LLM consumptionbashcrv "https://youtu.be/VIDEO_ID" -o crv-out --grid --why "what the user wants to know"
--grid — tiles frames into 3x3 contact sheets (cuts image count ~9x)--why — focuses the analysis on a specific questionbashcrv lecture.mp4 -o out --lang en
bashcrv clip.mp4 --no-transcribe
bashcrv "https://..." --cookies cookies.txt crv "https://..." --cookies-from-browser chrome
bashcrv tutorial.mp4 --adaptive
bashcrv "https://youtu.be/..." --why "pricing strategy" --kb ~/notes
bashcrv video.mp4 --viewer # Opens viewer.html — video + keyframes + transcript, fully offline
When a user shares a video (URL or file path):
--grid and --why:bash crv "<url-or-path>" -o crv-out --grid --why "<user's question>" For long videos, cap frames: --max-frames 60
Use one output folder per video (e.g. -o crv-out/<slug>). A folder that already holds an analysis is refused; pass --overwrite to replace it.
MANIFEST.txt first — it summarizes the run (frame counts, frames dir) and includes the transcript. Frames are named in chronological order; per-segment transcript timings live in transcript.json when available (there are no per-frame timestamps).crv-out/grids/ (each is a 3x3 sequence of consecutive keyframes, chronological). Only read individual crv-out/frames/*.jpg when you need a close-up.transcript.json) where available.| Flag | Default | Description | |---|---|---| | source (positional) | — | Video URL or local file path | | -o, --out | crv-out | Output directory | | --overwrite | off | Replace a previous analysis living in the output directory (without this, a non-empty output dir is refused to avoid mixing videos) | | --scene | 0.30 | Scene-change sensitivity (0-1, lower = more frames) | | --fps-floor | 1.0 | Guarantee at least one frame every N seconds | | --max-frames | 150 | Hard cap on total frames | | --adaptive | off | Adaptive scene detection for slow-changing content | | --text-anchors | off | Force frames at subtitle-cue timestamps — needs a sidecar .srt/.vtt or embedded subtitle track (burned-in captions can't be detected) | | --lang | auto | Whisper language (en, zh, auto, etc.) | | --cookies | — | Netscape cookie file for login-gated sources | | --cookies-from-browser | — | Read cookies from browser (chrome, safari, firefox, edge) | | --no-transcribe | off | Skip audio transcription | | --viewer | off | Write a local viewer.html | | --whisper-model | base | Whisper model size (tiny, base, small, medium, large, turbo — turbo: near large-v2 accuracy, ~8x faster) | | --dedup-threshold | 8 | % of pixels that must change for a new frame (higher = fewer frames kept) | | --dedup-window | 4 | Compare against last N kept frames (1 = consecutive-only) | | --report | off | Keep dropped frames + write report.html | | --why | — | Viewing intent, e.g. --why "find the pricing strategy" — focuses the model's analysis | | --grid | off | Tile frames into 3x3 contact sheets | | --kb | — | Save as dated markdown note to knowledge-base folder | | --keep-audio | off | Save full soundtrack as audio.m4a (for Gemini, GPT-4o, etc.) |
pythonfrom claude_real_video import process result = process("https://youtu.be/...", "out", lang="en") print(result.frame_count, result.transcript_path)
crv-out/
├── MANIFEST.txt # Summary for the LLM
├── frames/ # Deduplicated keyframes
├── transcript.txt # Plain-text transcript
├── grids/ # 3x3 contact sheets (with --grid)
├── audio.m4a # Full soundtrack (with --keep-audio)
├── viewer.html # Local viewer (with --viewer)
├── report.html # Dedup report (with --report)
└── dropped/ # Dropped frames (with --report)--grid — it dramatically reduces token usage while preserving visual continuity.--why — it focuses the analysis on what the user actually cares about.--max-frames 60 for long videos (>10 min) to stay within context limits.--no-transcribe when the user only cares about visuals (thumbnails, UI, slides).--keep-audio when the user asks about music, tone, or sound effects.--adaptive for screencasts, tutorials, or slow-moving content.MANIFEST.txt before frames — it has the run summary and the transcript.transcript.json when it exists (e.g., "At 0:42, the presenter says..."); frames themselves carry order, not timestamps.--overwrite to replace it.--cookies option is for your own authorized access.Other measured skills in the registry, with their headline benchmark lift.