How to Extract Frames from a Video at Specific Timestamps Using Claude Video
Claude Video's watch skill extracts exact frames at any timestamp you specify using the --timestamps flag, which calls extract_at_timestamps() in skills/watch/scripts/frames.py to perform FFmpeg-based seek and capture.
You can extract frames from a video at specific timestamps using Claude Video's watch skill, which supports local files and URLs with flexible time formatting. The workflow centers on the extract_at_timestamps() function in skills/watch/scripts/frames.py, invoked from the watch entry point in skills/watch/scripts/watch.py.
Passing Timestamps to the Watch Command
Use the --timestamps flag to supply a comma-separated list of times when running the watch command.
watch "https://youtu.be/ABC123" --timestamps "00:05,00:30,02:15"
The watch.py entry point parses this string through parse_timestamps() → parse_time() in skills/watch/scripts/frames.py, converting human-readable times into seconds before extraction begins.
How Frame Extraction Works Internally
The extract_at_timestamps() function performs five sequential operations to generate frame images.
1. Prepare Output Directory
The function clears any existing cue_*.jpg files from the target directory to prevent collisions.
out_dir.mkdir(parents=True, exist_ok=True)
for existing in out_dir.glob("cue_*.jpg"):
existing.unlink()
2. Clamp to Focus Window
Timestamps outside optional --start/--end ranges are filtered out. The logic uses lo = start_seconds or 0.0 and hi = end_seconds if end_seconds is not None else float("inf") to define valid windows.
3. Apply Frame Cap
When max_frames is set and more timestamps exist than the limit, the function calls _even_indices to evenly sample while preserving the first and last cues.
if max_frames is not None and len(in_window) > max_frames:
indices = _even_indices(len(in_window), max_frames)
selected = [in_window[i] for i in indices]
4. Execute FFmpeg Extraction
For each selected timestamp, the function builds and runs an FFmpeg command:
cmd = [
"ffmpeg",
"-ss", str(t),
"-i", video_path,
"-frames:v", "1",
"-q:v", "2",
"-y",
str(out_path)
]
subprocess.run(cmd, check=True, capture_output=True)
This writes JPEG files prefixed with cue_ (e.g., cue_0001.jpg) to avoid conflicts with regular detail frames.
5. Return Metadata
The function returns a metadata dictionary containing counts of requested, selected, and dropped timestamps.
Supported Timestamp Formats
Claude Video accepts multiple time formats in the --timestamps argument:
- Seconds only:
12or12.5 - Minutes:Seconds:
01:30or01:30.250 - Hours:Minutes:Seconds:
00:05:00or00:05:00.500
Fractional seconds are supported for precise frame alignment.
Combining Cue Frames with Detail Frames
After extraction, watch.py merges cue frames with regular detail frames through merge_frames() so both appear in the final markdown report. Cue frames retain their transcript-cue reason code, distinguishing them from automatically selected frames.
watch /path/to/video.mp4 \
--timestamps "00:10,01:00,01:30,02:00" \
--detail balanced \
--max-frames 50
Programmatic API Usage
Import extract_at_timestamps directly for custom Python workflows:
from pathlib import Path
from skills.watch.scripts.frames import extract_at_timestamps
video = "/tmp/video.mp4"
out_dir = Path("/tmp/frames")
timestamps = [12.0, 30.5, 125.0]
frames, meta = extract_at_timestamps(
video_path=video,
out_dir=out_dir,
timestamps=timestamps,
resolution=512,
max_frames=10
)
print("Extracted frames:", frames)
print("Metadata:", meta)
Key Source Files
| File | Purpose |
|---|---|
skills/watch/scripts/watch.py |
Entry point parsing --timestamps and orchestrating extraction |
skills/watch/scripts/frames.py |
Core extract_at_timestamps() implementation with FFmpeg logic |
skills/watch/scripts/config.py |
Default detail levels and frame caps |
skills/watch/scripts/download.py |
URL handling via YT-DLP |
skills/watch/scripts/transcribe.py |
Subtitle parsing for transcript-derived timestamps |
Summary
- Use
--timestamps "time1,time2,time3"to extract specific frames from any video source - Timestamps support seconds,
MM:SS, orHH:MM:SSformats with optional decimals - The
extract_at_timestamps()function inskills/watch/scripts/frames.pyhandles FFmpeg execution and file naming - Cue frames are prefixed with
cue_and merged with detail frames in final reports - Optional
--start/--endwindows and--max-framescaps control extraction scope
Frequently Asked Questions
What timestamp formats does Claude Video accept?
Claude Video accepts raw seconds (45.5), MM:SS (01:30), or HH:MM:SS (00:05:00) formats. Fractional seconds are supported for millisecond-precision frame extraction.
Where are extracted frames saved?
Frames are written to <work-dir>/frames/ alongside regular detail frames, using the cue_*.jpg naming convention to prevent clashes with automatically extracted frames.
Can I limit how many cue frames are extracted?
Yes. Pass --max-frames N to cap the total. When more timestamps are supplied than the cap, the system evenly samples across your list while preserving the first and last timestamps.
How do I extract frames from a YouTube video?
Provide the URL as the first argument to watch. The download.py module handles retrieval via YT-DLP before frame extraction proceeds:
watch "https://youtu.be/ABC123" --timestamps "00:30,01:15"
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →