How the `--max-frames` Flag Overrides Detail-Mode Frame Caps in Claude Video

The --max-frames argument sets a hard ceiling that supersedes any internal detail-mode or uniform-mode budget calculations, ensuring the final extracted frame count never exceeds the user-specified limit regardless of video duration.

In the bradautomates/claude-video repository, the skills/watch/scripts/frames.py script orchestrates all frame-extraction strategies. When processing video content, the engine normally calculates an optimal frame budget based on detail modes, but the --max-frames override interacts with these detail mode caps by taking precedence at every enforcement point in the pipeline.

How --max-frames Interacts with Detail Mode Caps

The --max-frames command-line option provides an absolute upper bound that takes precedence over every internal "detail-mode" cap the engine would otherwise apply. When a user specifies this flag, the value propagates through the extraction pipeline and overrides the duration-based budget calculations normally performed by auto_fps() (uniform mode) or auto_fps_focus() (detail mode).

According to the source code in skills/watch/scripts/frames.py, this override occurs at multiple stages: during initial FPS calculation, at the ffmpeg execution layer, and during post-processing sampling. This ensures that regardless of how the detail-mode logic calculates the "ideal" frame density, the output never exceeds the user-defined ceiling.

The Frame Budget Calculation Pipeline

CLI Parsing and Argument Propagation

In the CLI entry point (lines 1000–1012), the argument parser stores the --max-frames value in the max_frames variable. This value is then supplied to all extraction functions, including auto_fps(), auto_fps_focus(), and the various extraction helpers.


# Conceptual flow from frames.py L1000-L1012

max_frames = args.max_frames  # User-specified ceiling

extract(video_path, max_frames=max_frames, ...)

FPS Clamping Logic in _clamp_fps

Both auto_fps() and auto_fps_focus() ultimately invoke the _clamp_fps() helper function (lines 49–53) to finalize the frame budget. This function explicitly clamps the target frame count to the supplied max_frames:

def _clamp_fps(fps: float, duration_seconds: float, max_frames: int) -> tuple[float, int]:
    fps = min(fps, MAX_FPS)                         # never exceed MAX_FPS

    target = min(max_frames, max(1, int(round(fps * duration_seconds))))
    return fps, target

Here, the target calculation uses min(max_frames, ...) to ensure that even if the detail-mode logic calculates a higher frame budget based on video duration, the final target is capped at the user-supplied value.

Enforcement Points Throughout the Extraction Pipeline

The max_frames limit is enforced at three critical stages to guarantee compliance:

Early Enforcement During FPS Calculation

Before any frames are extracted, the _clamp_fps() function applies the first layer of enforcement. Whether the engine is operating in uniform mode (auto_fps) or focused detail mode (auto_fps_focus), the calculated target is immediately constrained by the --max-frames value.

FFmpeg Output Limits (lines 94–100)

The max_frames value is passed directly to the ffmpeg command via the -frames:v flag in the extract() function (lines 95–96). This hard limit at the codec level ensures that even if the frame selection logic fails, the output file count cannot exceed the specified maximum.


# From extract() in frames.py L94-L100

command = [
    "ffmpeg",
    "-i", video_path,
    "-frames:v", str(max_frames),  # Hard limit at ffmpeg level

    ...
]

Scene Candidate Extraction (lines 58–60)

For scene-based extraction strategies, the extract_scene_candidates() function (lines 58–60) also receives the max_frames parameter, ensuring that the initial candidate pool generation respects the user ceiling.

Post-Processing Caps After Deduplication

For scene and keyframe engines, the script discovers candidate frames, optionally deduplicates them, then applies an even-sample cap using _even_sample(). This final filtering step (referenced in extract_scene_or_uniform at lines 44–46 and extract_keyframes at lines 74–76) again respects the max_frames argument, ensuring that the final delivered frame count stays within bounds even after content analysis.

Practical Examples

These examples demonstrate how --max-frames overrides the default detail-mode budgets:

Uniform mode with default caps:


# 30-second video defaults to ~12 frames (detail-mode budget)

python -m skills.watch.scripts.frames video.mp4 out/

Override with strict cap:


# Forces exactly 5 frames regardless of video duration

python -m skills.watch.scripts.frames video.mp4 out/ --max-frames 5

In this case, _clamp_fps() forces the target to 5, ffmpeg receives -frames:v 5, and post-processing sampling respects the 5-frame ceiling.

Focused detail mode with range limits:


# Detail mode would normally select ~30 frames for a 3-second clip

python -m skills.watch.scripts.frames video.mp4 out/ --start 00:01 --end 00:04 --max-frames 10

Here, auto_fps_focus() would calculate a dense budget of approximately 30 frames, but _clamp_fps() limits the final count to 10 before extraction begins.

Summary

  • The --max-frames flag provides a hard ceiling that supersedes duration-based budgets calculated by detail mode (auto_fps_focus) or uniform mode (auto_fps).
  • The limit is enforced at three stages: during FPS calculation via _clamp_fps() (lines 49–53), at the ffmpeg extraction step via -frames:v (lines 94–100), and during post-processing through _even_sample() (lines 44–46, 74–76).
  • Both uniform extraction and focused detail extraction respect the same override mechanism, ensuring consistent behavior across all processing modes.
  • The override is idempotent—specifying a --max-frames value higher than the calculated budget has no effect, while lower values forcibly constrain the output.

Frequently Asked Questions

Does --max-frames affect both uniform and detail modes?

Yes. The flag is passed to both auto_fps() (uniform mode) and auto_fps_focus() (detail mode) in skills/watch/scripts/frames.py. Both functions rely on _clamp_fps() to enforce the limit, meaning the override applies regardless of which extraction strategy the engine selects.

At what stage does the max-frames limit apply?

The limit is applied at three distinct stages: first during the FPS budget calculation inside _clamp_fps() (lines 49–53), second at the ffmpeg command level via the -frames:v argument (lines 94–100), and third during post-processing when _even_sample() caps the final frame list (lines 44–46 and 74–76).

What happens if --max-frames is higher than the detail-mode budget?

If the user-specified limit exceeds the calculated detail-mode budget, the budget calculation takes precedence. The min(max_frames, ...) logic in _clamp_fps() ensures that the lower of the two values is used, so the engine extracts only what the detail-mode logic deems necessary, never exceeding the calculated budget unless forced by the user cap.

Does the limit apply before or after deduplication?

The --max-frames limit applies both before and after deduplication. The initial ffmpeg extraction is capped at the limit (pre-deduplication), and the final _even_sample() step (lines 44–46, 74–76) applies an even-sample cap to the deduplicated candidate set, ensuring the final output never exceeds the specified ceiling even if duplicate frames are removed from the initial pool.

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 →