# How to Extract Frames at Specific Timestamps Using the `--timestamps` Option in claude-video

> Easily extract frames at specific absolute timestamps from videos using claude-video's --timestamps option. Learn how to get exact frame captures for your projects.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: how-to-guide
- Published: 2026-08-10

---

**Pass a comma-separated list of timestamps to [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) with `--timestamps` to extract exact frames at those positions—for example, `--timestamps 4:32,7:10,9:55` creates `cue_0000.jpg`, `cue_0001.jpg`, and `cue_0002.jpg`.**

The `claude-video` repository provides a frame extraction engine that lets you request precise video frames by absolute timestamps. This feature is implemented in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) and exposed through the [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) CLI entry point. Whether you need frames at specific transcript cues or arbitrary time positions, the `--timestamps` option gives you direct control over which moments get captured.

## Parsing Timestamp Strings with `parse_timestamps()`

The first step in the extraction pipeline converts raw timestamp strings into normalized floating-point seconds.

In [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) (lines 95–103), the `parse_timestamps()` function:

- Splits comma-separated values (e.g., `"4:32,7:10,9:55"`)
- Parses each token as `MM:SS` or `HH:MM:SS` format
- Returns a **sorted, de-duplicated list** of seconds

```python
from skills.watch.scripts.frames import parse_timestamps

timestamps = parse_timestamps("4:32,7:10,9:55")
print(timestamps)  # [272.0, 430.0, 595.0]

```

Deduplication and sorting ensure predictable output and prevent redundant ffmpeg invocations.

## Selecting Valid Frames with `extract_at_timestamps()`

Once parsed, timestamps are filtered against user constraints before extraction begins.

The `extract_at_timestamps()` function (lines 124–158 in [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py)) performs three operations:

1. **Range filtering** — Drops timestamps outside `--start`/`--end` window boundaries
2. **Even-sampling capping** — Applies `_even_indices()` if `max_frames` limits the total cue count
3. **Metadata preparation** — Builds frame dictionaries with `"reason": "transcript-cue"`

This design lets you specify many timestamps while respecting overall frame budgets. Cue frames are never silently dropped after extraction—they're protected through the merge step described below.

## Extracting JPEG Frames via ffmpeg

For each retained timestamp, the engine spawns an ffmpeg subprocess that seeks exactly to the requested position.

In [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py) (lines 160–175), the extraction logic:

```python

# Simplified representation of the actual implementation

cmd = [
    "ffmpeg",
    "-ss", str(timestamp),  # seek to absolute position

    "-i", str(video_path),
    "-frames:v", "1",       # output exactly one frame

    "-q:v", "2",            # high-quality JPEG

    f"cue_{idx:04d}.jpg"
]

```

The `-ss` parameter precedes `-i` for **fast, input-accurate seeking**—critical for processing long videos efficiently. Output files follow the pattern `cue_0000.jpg`, `cue_0001.jpg`, etc., maintaining chronological correspondence with the input list.

## Merging Cue Frames into the Final Frame Set

Cue frames coexist with frames from other extraction engines through `merge_frames()` (lines 112–119 in [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py)).

Key merge behaviors:

- **Preserves chronological order** across all frame sources
- **Re-indexes** the combined list for consistent referencing
- **Protects cue frames** from downstream even-sampling that might affect scene/keyframe selections

This matters when combining `--timestamps` with `--detail balanced` or `high` modes. Your explicitly requested frames remain guaranteed in the output.

## Complete CLI Example

Request three exact frames from a YouTube video:

```bash
python3 "$SKILL_DIR/scripts/watch.py" "https://youtu.be/abc123" \
  --detail balanced \
  --timestamps 4:32,7:10,9:55

```

Execution flow:

1. Downloads the video stream (if not cached)
2. Parses timestamps to `[272.0, 430.0, 595.0]`
3. Extracts `cue_0000.jpg`, `cue_0001.jpg`, `cue_0002.jpg`
4. Includes them in final JSON with `"reason": "transcript-cue"`

## Programmatic Usage Without the CLI

Call the frame engine directly for custom workflows:

```python
from pathlib import Path
from skills.watch.scripts.frames import (
    parse_timestamps,
    extract_at_timestamps,
)

video_path = "/tmp/video.mp4"
out_dir = Path("/tmp/frames")

timestamps = parse_timestamps("4:32,7:10,9:55")
frames, meta = extract_at_timestamps(
    video_path,
    out_dir,
    timestamps,
    resolution=512,
    max_frames=None,  # keep all cue frames

)

print(frames)  # [{'path': 'cue_0000.jpg', 'timestamp_seconds': 272.0, ...}]

print(meta)    # {'engine': 'timestamps', 'requested': 3, 'extracted': 3}

```

Combine with scene-based extraction:

```python
from skills.watch.scripts.frames import extract_scene_or_uniform, merge_frames

scene_frames, _ = extract_scene_or_uniform(video_path, out_dir, detail="balanced")
cue_frames, _ = extract_at_timestamps(video_path, out_dir, timestamps)

all_frames = merge_frames(scene_frames, cue_frames)

```

## Summary

- **`parse_timestamps()`** (lines 95–103) converts `"MM:SS,MM:SS"` strings to sorted float seconds
- **`extract_at_timestamps()`** (lines 124–158) filters by range, applies caps, and prepares frame metadata
- **ffmpeg seeks** (`-ss`) generate `cue_*.jpg` files (lines 160–175)
- **`merge_frames()`** (lines 112–119) protects cue frames in mixed-engine outputs
- **`--timestamps`** integrates with all `--detail` modes without losing your requested frames

## Frequently Asked Questions

### What timestamp formats does `--timestamps` accept?

The parser accepts `MM:SS` and `HH:MM:SS` formats with comma separation. Values like `"4:32,7:10,9:55"` and `"1:30:00,2:15:30"` both work. Colons are required—decimal seconds like `"4.5"` are not supported by default.

### Do timestamps outside the `--start`/`--end` window cause errors?

No. The `extract_at_timestamps()` function silently drops out-of-range timestamps before extraction. Only valid frames within your specified window are processed, preventing wasted ffmpeg calls.

### How do cue frames differ from scene or keyframe selections?

Cue frames receive `"reason": "transcript-cue"` in their metadata and are produced by timestamp-specific seeking rather than content analysis. They merge with scene/keyframe outputs but bypass the visual analysis pipeline used for automatic scene detection.

### Can I use `--timestamps` with `--max-frames` limits?

Yes. The engine applies even-sampling to your timestamp list if the count exceeds `max_frames`, similar to how scene frames get sampled. However, once extracted, cue frames are protected by `merge_frames()` and won't be dropped by later sampling stages applied to other frame types.