How Timestamps Are Parsed in `--timestamps` Mode and Prioritized in claude-video

The --timestamps flag parses comma-separated time strings into sorted, unique seconds, extracts one frame per timestamp, and prioritizes these cue frames above all other automatically selected frames.

The bradautomates/claude-video repository provides a powerful video analysis interface where users can extract specific frames at exact moments using the --timestamps flag. Understanding how timestamps are parsed in --timestamps mode and their prioritization helps you control exactly which frames appear in your analysis. This guide examines the source code implementation in skills/watch/scripts/frames.py to explain the parsing logic, extraction pipeline, and frame priority rules.

Timestamp Parsing Logic in frames.py

The core parsing functionality resides in skills/watch/scripts/frames.py, where the parse_timestamps() function converts raw user input into a clean list of seconds.

The parse_timestamps() Function

According to the source code at lines 95-103, parse_timestamps() processes the input string through several normalization steps:

  • The raw string is split on commas
  • Each token is stripped of surrounding whitespace
  • Empty tokens are ignored
  • Each non-empty token is passed to parse_time() for format conversion

The resulting float values are collected, de-duplicated using set(), and sorted into ascending order.

Supported Time Formats

The underlying parse_time() function (lines 55-72) accepts three distinct formats:

  • SS – Seconds only (e.g., 30)
  • MM:SS – Minutes and seconds (e.g., 1:05)
  • HH:MM:SS – Hours, minutes, and seconds (e.g., 1:30:45)

All formats optionally support fractional seconds for precise frame extraction.

Example transformation:


"30,1:05,90" → [30.0, 65.0, 90.0]
" 90 , 30, 30 " → [30.0, 90.0]

Cue Frame Extraction and Sampling

Once parsed, the timestamp list flows into extract_at_timestamps() at lines 124-132, which manages the actual frame extraction pipeline.

Filtering by Focus Window

The function first validates each timestamp against the current focus window ([start, end]). Timestamps falling outside this window are dropped from the candidate list, ensuring only relevant frames are processed.

Even Sampling When Over Limit

If a max_frames limit is configured and the surviving timestamp count exceeds this budget, the system applies _even_indices() (lines 84-92) to perform even sampling. This algorithm preserves the first and last timestamps while distributing selections evenly across the time range. Each retained timestamp generates exactly one frame extracted via ffmpeg and saved as cue_*.jpg.

Prioritization of Cue Frames Over Automatic Selection

Cue frames receive special treatment in the frame selection hierarchy, guaranteeing their inclusion regardless of other constraints.

Merge Logic in merge_frames()

The merge_frames() function (lines 12-20) combines outputs from the automatic detail engine (scene/keyframe/uniform sampling) with the cue-frame engine. Because the implementation concatenates the cue list before sorting chronologically, cue frames are always kept and never discarded by later capping logic applied to the detail engine. This architectural choice ensures explicit user requests take precedence over algorithmic selections.

Interaction with --detail transcript Mode

When using --detail transcript alongside --timestamps, the behavior shifts significantly. As implemented in skills/watch/scripts/watch.py at lines 107-112, the transcript-detail path intentionally returns only the cue frames, skipping the normal detail engine entirely. This creates a focused analysis mode where you receive exactly the frames you specified plus transcript data, without additional scene or keyframe sampling.

Practical Usage Examples

Basic timestamp extraction:


# Grab frames at three explicit moments (30 s, 1 min 5 s, 90 s)

claude-video watch myvideo.mp4 --timestamps 30,1:05,90

Programmatic access:

from skills.watch.scripts.frames import parse_timestamps, extract_at_timestamps
from pathlib import Path

# Parse a user-supplied timestamps string

seconds = parse_timestamps("30, 1:05, 90")

# → [30.0, 65.0, 90.0]

# Extract one frame per timestamp (saving to ./out)

frames, meta = extract_at_timestamps(
    video_path="myvideo.mp4",
    out_dir=Path("./out"),
    timestamps=seconds,
    resolution=512,
    max_frames=None,
)
print(meta)

# {'engine': 'timestamps', 'candidate_count': 3,

#  'selected_count': 3, 'dropped_out_of_window': 0, 'fallback': False}

Transcript-only mode with cues:

claude-video watch myvideo.mp4 --detail transcript --timestamps 4:32,7:10,9:55

# Output: cue frames only – no additional scene/keyframe frames.

Summary

  • Parsing pipeline: parse_timestamps() splits on commas, cleans whitespace, and converts to sorted unique seconds using parse_time() for SS, MM:SS, or HH:MM:SS formats.
  • Extraction logic: extract_at_timestamps() filters by focus window, applies even sampling if over budget, and generates cue_*.jpg files via ffmpeg.
  • Priority guarantee: Cue frames are concatenated first in merge_frames(), ensuring they survive any frame budget caps applied to automatic selection engines.
  • Transcript mode: Combining --detail transcript with --timestamps returns only cue frames, bypassing scene and keyframe analysis entirely.

Frequently Asked Questions

What time formats does --timestamps accept?

The parse_time() function in skills/watch/scripts/frames.py accepts three formats: raw seconds (30), minutes and seconds (1:05), or hours, minutes, and seconds (1:30:45). All formats support optional fractional seconds for sub-second precision.

How does claude-video handle duplicate or out-of-order timestamps?

The system automatically de-duplicates timestamps using set() and sorts them numerically before extraction. Whitespace around entries is stripped, and empty tokens are ignored, so inputs like " 90 , 30, 30 " normalize to [30.0, 90.0].

Do cue frames count against the max_frames budget?

During the initial extraction phase, yes—extract_at_timestamps() applies _even_indices() to downsample if you provide more timestamps than max_frames allows. However, once the cue list is generated, these frames are protected from any subsequent capping logic when merged with automatic selections.

What happens when I combine --timestamps with --detail transcript?

As implemented in skills/watch/scripts/watch.py lines 107-112, this combination triggers a cue-only mode that returns exclusively the frames at your specified timestamps. The normal detail engine (scene/keyframe/uniform sampling) is bypassed entirely, giving you precise visual control alongside transcript analysis.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →