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.

License: MIT Rust Hermes Agent GitHub stars Version

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 version field in Cargo.toml (SemVer 2.0.0).
  • Tags: annotated git tags vX.Y.Z point 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.


License

MIT. Built on yt-dlp, ffmpeg, av-scenechange. Whisper transcription via Groq or OpenAI.

Original: bradautomates/claude-video