watch2 — Video Analysis for AI Agents
It watches. It listens. It verifies. Rust-powered video analysis skill for Hermes Agent — transcript-first with scene detection. Cross-references frames against captions to catch what either one misses.
Works with: Hermes Agent · Claude Code · Codex · Any AI agent that reads files
Paste a URL or a local path. Hermes fetches captions, downloads the video, detects scene changes, extracts frames at key moments, and cross-references the transcript against what's actually on screen. Auto-captions misspell names? It catches that. A claim doesn't match the visual? It flags that.
Zero config to start. yt-dlp, ffmpeg, and av-scenechange are the only runtime dependencies. Captions cover most public videos for free. Whisper API key is only needed when a video has no captions.
Quick Install
Hermes Agent (recommended):
hermes skill install watch2
From source:
git clone https://github.com/m1crodevil/hermes-video-rs && cd hermes-video-rs
cargo build --release
sudo cp target/release/watch2 /usr/local/bin/
Runtime dependencies: yt-dlp, ffmpeg, ffprobe, av-scenechange
What People Use It For
Analyze someone else's content.
watch2 https://youtu.be/ what hook did they open with?
Diagnose a bug from a video.
watch2 bug-repro.mov what's going wrong?
Summarize a video.
watch2 https://youtu.be/ summarize this
Catch what captions get wrong.
watch2 https://youtu.be/ are any names or terms misspelled in the captions?
How It Works
watch2 runs a single linear pipeline — no mode branching, no configuration trees:
Video URL / local path
↓
1. Detect language via yt-dlp metadata (quick, no download)
↓
2. Download video (720p) + targeted subtitles (JSON3) via yt-dlp
↓
3. Parse transcript from best-matching subtitle file
↓
4. Whisper fallback (if no captions and API key available)
↓
5. Scene detection via av-scenechange
↓
6. Agent reads report.json → selects key moments via tiered LLM priority (hook-first, impact-scored) → extracts frames
↓
7. Cleanup video file (save disk space)
↓
8. Build WatchReport (markdown/JSON)
The binary handles data extraction only. All intelligence (LLM calls, moment selection, analysis) is handled by the agent. No moments_prompt.txt, no key_moments.json — the agent reads report.json and decides what to analyze.
Cross-Reference Methodology
Every vision finding is classified:
- ✅ confirmed — vision matches transcript
- 🔧 corrected — vision shows different spelling/entity
- ❓ fabrication — claim has no visual evidence
- ⚠️ unverified — cannot determine from visual alone
- 🔸 partial — partially shown on screen
Skill Architecture
The skill uses progressive disclosure — the agent loads only what it needs:
Tier 1: skill_view('watch2') → 216-line core (~800 tokens)
Tier 2: skill_view('watch2', file_path) → reference files on-demand
Core (SKILL.md): Quick reference, output format, CLI options, configuration
References (references/): Detailed workflows, pitfalls, visual verification rules (16 files)
This keeps token cost minimal (~800 tokens per invocation vs ~12K before) while providing full context when needed. Based on Hermes Agent's 4-tier progressive disclosure model.
Key Features
| Feature | Detail |
|---|---|
| Transcript-first | JSON3 captions with word-level timing |
| Tiered moment selection | 3-tier priority: hooks → arguments → entities (impact-scored) |
| Standalone check | Rejects moments that need surrounding context |
| Anti-pattern filter | Skips intros, outros, filler, sponsor reads |
| Scene detection | av-scenechange for visual boundaries |
| Cross-reference | Frames vs transcript — catches misspellings, fabrications |
| Single binary | ~6MB, zero config, 5ms cold start |
| Agent-native | Outputs report.json, agent handles intelligence |
| Multi-platform | YouTube, TikTok, Vimeo, local files, any URL yt-dlp supports |
| Cache-aware | SHA256 dedup, skip re-downloads |
| Whisper fallback | Groq ($0.004/min) or OpenAI — only when no captions |
CLI Reference
# Basic usage
watch2 https://youtu.be/dQw4w9WgXcQ what happens at the 30 second mark?
watch2 https://www.tiktok.com/@user/video/123 summarize this
watch2 ~/Movies/screen-recording.mp4 when does the UI break?
watch2 https://vimeo.com/123 what tools does she mention?
| Flag | Description | Default |
|---|---|---|
--resolution W |
Frame width in pixels (128–4096) | 512 |
--out-dir DIR |
Custom working directory | temp dir |
--keep-video |
Retain downloaded video after processing | false |
--cookies |
Use Chrome cookies for yt-dlp (age-restricted videos) | false |
--no-whisper |
Disable Whisper fallback transcription | false |
--no-dedup |
Keep near-duplicate frames | false |
--output markdown|json|both |
Output format | markdown |
--no-cache |
Disable download cache | false |
--cache-dir DIR |
Custom cache directory | ~/.cache/watch2 |
--timestamps T |
Comma-separated timestamps for cue frame extraction (e.g. "00:30,01:15,02:45") | none |
Output Formats
| Format | Command | Use When |
|---|---|---|
| Markdown (default) | watch2 URL question |
Agent reads directly |
| JSON | watch2 URL question --output json |
Programmatic processing |
| Both | watch2 URL question --output both |
Agent + file storage |
The WatchReport includes: video metadata, extracted frames with timestamps, full transcript with word-level timing (when available from JSON3 captions), scene boundaries from av-scenechange, key moment metadata (LLM-selected moments with reasons), and warnings for sparse coverage or missing transcript.
API Keys & Configuration
Captions cover the majority of public videos for free. The Whisper fallback only kicks in when a video has no caption track.
| Capability | Requirement | Cost |
|---|---|---|
| Download + native captions | yt-dlp + ffmpeg |
Free |
| Agent-side moment selection | Agent LLM (via Hermes) | Included |
| Whisper fallback (preferred) | Groq API key | ~$0.004/min |
| Whisper fallback (alt) | OpenAI API key | Standard pricing |
| Disable Whisper | --no-whisper |
Free, frames-only |
Config file: ~/.config/watch/.env
GROQ_API_KEY=gsk_... # Optional — for Whisper fallback
OPENAI_API_KEY=sk-... # Optional — alternative Whisper provider
SETUP_COMPLETE=true
Architecture
watch2/
├── skill/watch2/
│ ├── SKILL.md # Core skill (216 lines, ~800 tokens)
│ └── references/ # On-demand reference files (16 files)
│ ├── agent-workflow.md # Full 8-step workflow
│ ├── pitfalls.md # Debugging reference
│ ├── moment-selection.md # Tiered priority + impact scoring
│ ├── transcript-moments-pipeline.md
│ ├── visual-verification.md
│ ├── reading-report.md
│ ├── scene-detection.md
│ └── ...
├── src/
│ ├── main.rs # Entry point — CLI, cache init, pipeline run
│ ├── cli.rs # clap CLI definition
│ ├── config.rs # Config loading (.env)
│ ├── pipeline.rs # Linear pipeline
│ ├── download.rs # yt-dlp wrapper with retry + caching
│ ├── transcript.rs # JSON3/VTT subtitle parser
│ ├── frames/
│ │ ├── mod.rs # auto-fps, scale filter, FrameMeta
│ │ ├── metadata.rs # ffprobe video metadata
│ │ └── timestamp.rs # Frame extraction at timestamps
│ ├── scene_detect.rs # av-scenechange integration
│ ├── output.rs # WatchReport structs + output
│ ├── cache.rs # Download cache (SHA256)
│ └── whisper.rs # Groq/OpenAI Whisper API
└── tests/ # Integration tests
Why Rust?
| Python (hermes-video) | Rust (hermes-video-rs) | |
|---|---|---|
| Startup | ~500ms (Python import) | ~5ms |
| Memory | ~50-100MB | ~5-15MB |
| Binary | 0 (needs Python runtime) | ~6MB self-contained |
| Install | pip + yt-dlp + ffmpeg | Single binary + yt-dlp + ffmpeg + av-scenechange |
| Tests | 1,379 LOC | 5,311 LOC (170 passing) |
Development
# Run all tests
cargo test
# Run specific test suites
cargo test test_cli
cargo test test_transcript
cargo test test_output
cargo test test_frames
# Build release
cargo build --release
# Install
sudo cp target/release/watch2 /usr/local/bin/
# Run with verbose output
RUST_LOG=debug cargo run -- --help
# Check installed version
watch2 --version
Versioning & Releases
- Source of truth: the
versionfield inCargo.toml(SemVer 2.0.0). - Tags: annotated git tags
vX.Y.Zpoint to the released commit (e.g.v8.1.0). - Releases: GitHub Releases mirror the tags, with notes generated from
CHANGELOG.md. - Changelog: maintained with git-cliff (
git-cliff --output CHANGELOG.md) from conventional commits. - Automation: cargo-release with
release.toml(publish disabled — binary only). Bump + tag + push:
cargo install cargo-release
cargo release patch --execute # or minor / major
Check the current version: watch2 --version
Related Projects
Note: This is a Rust rewrite of hermes-video — same features, 100× faster startup, single binary.
- bradautomates/claude-video — Original inspiration (7.6k stars)
- m1crodevil/hermes-video — Python version (same features, slower startup)
License
MIT. Built on yt-dlp, ffmpeg, av-scenechange. Whisper transcription via Groq or OpenAI.
Original: bradautomates/claude-video
No comments yet
Be the first to share your take.