claude-video

CLI Tool

bradautomates/claude-video

Give Claude the ability to watch and analyze any video.

Overview

A CLI tool that integrates with Claude to download videos, extract frames, and transcribe audio. It supports YouTube and many other sources, providing a complete video analysis pipeline. Users can ask questions about video content and get answers grounded in both visual and auditory information.

README Preview

# /watch\n\n**Give Claude the ability to watch any video.**\n\nClaude Code (recommended — auto-updates via marketplace):\n```\n/plugin marketplace add bradautomates/claude-video\n/plugin install watch@claude-video\n```\n\nCodex, Cursor, Copilot, Gemini CLI, or any of 50+ [Agent Skills](https://agentskills.io) hosts:\n```bash\nnpx skills add bradautomates/claude-video -g\n```\n(`-g` installs globally for your user, available across all projects. Drop it to scope per-project.)\n\nMore install options (claude.ai web, manual) in the [Install](#install) section below.\n\nZero config to start — `yt-dlp` and `ffmpeg` install on first run via `brew` on macOS (Linux/Windows print exact commands). Captions cover most public videos for free. Whisper API key is only needed when a video has no captions.\n\n---\n\nClaude can read a webpage, run a script, browse a repo. What it can't do, out of the box, is *watch a video*. You paste a YouTube link and it has to either guess from the title or pull a transcript that's missing 90% of what's on screen.\n\nWith Claude Video `/watch` you can paste a URL or a local path, ask a question, and Claude fetches captions first, downloads only what it needs, extracts frames (scene-aware, or fast keyframes at `efficient` detail), pulls a timestamped transcript (free captions when available, Whisper API as fallback), and `Read`s every frame as an image. By the time it answers, it has *seen* the video and *heard* the audio.\n\n```\n/watch https://youtu.be/dQw4w9WgXcQ what happens at the 30 second mark?\n```\n\n## What people actually use it for\n\n**Analyze someone else's content.** `/watch https://youtu.be/ what hook did they open with?` Claude looks at the first frames, reads the opening transcript, breaks down the structure. Same for ad creative, competitor launches, podcast intros, anything where the *how* matters as much as the *what*.\n\n**Diagnose a bug from a video.** Someone sends you a screen recording of something broken. `/watch bug-rep

FAQ (5)

Troubleshooting
How do I fix "UnicodeEncodeError: 'charmap' codec can't encode character '→'" when running a Python CLI on Windows?

This happens because Windows consoles often use cp1252 instead of UTF-8, while the report prints characters such as →, …, or —.

Temporary user workaround:

setx PYTHONUTF8 1

Close and reopen the terminal after running it. For only the current PowerShell session, use:

$env:PYTHONUTF8 = "1"

Permanent application fix: reconfigure stdout and stderr to UTF-8 at program startup, before any report output:

import sys

for stream in (sys.stdout, sys.stderr):
    try:
        stream.reconfigure(encoding="utf-8")
    except (AttributeError, ValueError):
        pass

Call this helper from every entry point, such as watch.py, frames.py, whisper.py, transcribe.py, setup.py, and download.py. TextIOWrapper.reconfigure() is available in Python 3.7+; the affected project requires Python 3.10+. Do not merely remove the non-ASCII characters, because other report output can trigger the same cp1252 error.

GitHub Issue #61
Troubleshooting
How do I fix "Unknown command: /watch" after installing watch@claude-video in Claude Code?

The slash command fails because Claude Code 2.1.126 does not parse the YAML inline-list format for allowed-tools. Edit ~/.claude/plugins/cache/claude-video/watch/0.1.2/commands/watch.md and replace:

allowed-tools: [Bash, Read, AskUserQuestion]

with:

allowed-tools: Bash, Read, AskUserQuestion

You can apply this directly with:

sed -i '' 's/^allowed-tools: \[Bash, Read, AskUserQuestion\]$/allowed-tools: Bash, Read, AskUserQuestion/' ~/.claude/plugins/cache/claude-video/watch/0.1.2/commands/watch.md

Fully quit and reopen Claude Code, then run /watch or select /watch:watch from autocomplete. The permanent fix is for the plugin maintainer to make this one-line change in commands/watch.md on main; adding frontmatter validation can prevent regression.

GitHub Issue #6
Troubleshooting
Why are the video title and uploader missing from /watch reports on Windows?

Upgrade to watch v0.1.3 or later. The bug occurs because scripts/download.py calls Path.read_text() without encoding="utf-8"; on Windows Python uses cp1252, so non-ASCII characters in yt-dlp's video.info.json cause UnicodeDecodeError. The broad except then silently leaves only the URL, causing title and uploader to be omitted. To patch older versions, change:

raw = json.loads(info_path.read_text())

to:

raw = json.loads(info_path.read_text(encoding="utf-8"))

Also log parse failures instead of silently ignoring them, for example:

except Exception as exc:
    print(f"[watch] info.json parse failed: {exc}", file=sys.stderr)
    info = {"url": url}

As a temporary workaround, re-read video.info.json from the output directory explicitly as UTF-8. If Windows console output fails on emoji or other non-ASCII title characters, set PYTHONUTF8=1 or PYTHONIOENCODING=utf-8 before running the command.

GitHub Issue #4
Troubleshooting
How do I prevent yt-dlp option injection when passing a user-supplied URL from Python subprocess?

Insert "--" immediately before the URL in the yt-dlp argv array so its parser stops processing options. Also validate the URL and reject inputs starting with -.

cmd = [
    "yt-dlp",
    "-N", "8",
    "-o", output_template,
    "--",
    url,
]
subprocess.run(cmd, check=True)

Harden URL validation as defense in depth:

from urllib.parse import urlparse

def is_url(source: str) -> bool:
    if source.startswith("-"):
        return False
    parsed = urlparse(source)
    return parsed.scheme in ("http", "https") and bool(parsed.netloc)

For ffmpeg/ffprobe, do not rely on -- because those tools do not treat it as end-of-options; resolve user-controlled paths to absolute paths with Path.resolve(). This issue was fixed in claude-video v0.1.3/commit c333c22.

GitHub Issue #2
Troubleshooting
How can I fix misheard words in auto-generated video transcripts using claude-video?

There is currently no one-click option that writes a corrected VTT/SRT file, but a two-pass workflow works:

1. Run /watch <url> --detail transcript and ask Claude for the raw timestamped transcript plus suspicious segments, such as proper nouns, homophones, and abrupt context changes. For already-captioned URLs, the tool uses the VTT pulled by yt-dlp and skips downloading the video.
2. Download the video and recheck only the questionable timestamps:

/watch <local-video> --detail transcript --timestamps 1:23,4:56,7:08 --no-whisper

Claude extracts frames only at those timestamps, compares them with the transcript, and can suggest context-aware corrections. Apply those corrections manually to the VTT/SRT file.

GitHub Issue #66