How the MAX_FPS Cap of 2.0 Impacts Frame Selection in claude-video
The MAX_FPS = 2.0 hard ceiling in claude-video ensures frame extraction never exceeds 2 frames per second, enforcing token budget compliance by clamping calculated rates regardless of video length or the --max-frames parameter.
The MAX_FPS constant sits at the heart of claude-video's frame selection algorithm in bradautomates/claude-video. This repository implements a Claude-powered video analysis tool that extracts visual frames for LLM consumption, balancing comprehensiveness against token limits. Understanding how this 2.0 FPS cap shapes frame selection helps users predict behavior across different video durations and optimize their --max-frames settings.
Where MAX_FPS Is Defined and Enforced
In skills/watch/scripts/frames.py, the constant is declared at module level:
MAX_FPS = 2.0
Source: skills/watch/scripts/frames.py#L19
This value feeds into the _clamp_fps helper function, which applies the ceiling before any final frame calculations:
def _clamp_fps(fps: float) -> float:
return min(fps, MAX_FPS)
Source: skills/watch/scripts/frames.py#L49-L52
Both automatic FPS calculation paths—auto_fps for standard mode and auto_fps_focus for focused frame selection—route their computed target rates through _clamp_fps. This architectural choice guarantees the 2.0 FPS limit applies universally, regardless of which extraction strategy is active.
How Frame Selection Works Under the Cap
Claude-video uses a budget-driven extraction model. Rather than extracting at a fixed rate, it calculates what FPS would hit the user-specified --max-frames limit (default 100) given the video's duration. The MAX_FPS cap then truncates this calculation.
The mathematical flow is:
- Compute
target_fps = max_frames / duration_seconds - Apply
actual_fps = min(target_fps, MAX_FPS) - Derive final frame count:
total_frames = actual_fps × duration
This creates two distinct behavioral regimes based on video length.
Impact on Long vs. Short Videos
Long Videos: Cap-Enforced Sparsity
For videos exceeding 50 seconds with default settings, the budget math would suggest FPS below 2.0 anyway (100 frames ÷ 50s = 2.0 fps). For longer content, the budget itself limits extraction before the cap engages.
However, with elevated --max-frames values (e.g., 300 or 500), the cap becomes the active constraint. A 5-minute video with --max-frames 600 would mathematically support 2.0 fps exactly—but cannot exceed it. The cap thus protects token budgets from users who might otherwise request frame-dense analysis of lengthy content.
Short Videos: Density at the Ceiling
For videos under 50 seconds, the budget math often produces target FPS above 2.0. Consider a 10-second clip with default --max-frames 100:
- Uncapped calculation: 100 ÷ 10 = 10.0 fps
- After
_clamp_fps: 2.0 fps - Actual frames extracted: 20 frames
The cap preserves temporal density up to the limit but prevents over-sampling that would waste tokens on near-duplicate frames. This is particularly relevant for auto_fps_focus mode, which attempts denser extraction around detected scene changes—the cap ensures even this aggressive mode respects the 2.0 ceiling.
Practical Configuration Implications
Users cannot override MAX_FPS through CLI flags. The constant is hardcoded, making the 2.0 ceiling a non-negotiable system constraint according to the claude-video source code.
To maximize frame coverage:
- Increase
--max-framesrather than expecting higher density—this extends the cap's reach across longer durations - Split long videos into shorter segments if scene-level granularity is critical
- Use
--focusmode (auto_fps_focus) to concentrate the 2.0 fps budget on high-information regions rather than uniform sampling
Summary
MAX_FPS = 2.0inskills/watch/scripts/frames.pyenforces a hard extraction ceiling_clamp_fpsapplies this limit to bothauto_fpsandauto_fps_focuscalculations- Short videos hit the cap and extract at exactly 2.0 fps despite higher budget allowances
- Long videos may fall below the cap based on
--max-frames÷ duration math - The cap is immutable via configuration—users must work within its constraints through frame budget allocation and video segmentation
Frequently Asked Questions
What is the exact value of MAX_FPS in claude-video?
The MAX_FPS constant is set to 2.0 at line 19 of skills/watch/scripts/frames.py. This value has remained fixed in the repository's main branch and cannot be modified through command-line arguments or configuration files.
Can I extract more than 2 frames per second from a short video?
No. Even with --max-frames set higher than your video duration would require at 2.0 fps, the _clamp_fps function enforces the ceiling. A 5-second video with --max-frames 100 still extracts only 10 frames (2.0 fps × 5s), not 100 frames. The cap takes precedence over the budget calculation when the budget would permit higher rates.
Why does claude-video limit frame extraction to 2 FPS?
The 2.0 FPS cap serves as a token economy mechanism. Claude's vision capabilities consume significant context window per image; unconstrained frame rates from short videos could rapidly exhaust available tokens. The cap ensures predictable, bounded resource consumption across all video lengths while preserving sufficient visual information for analysis tasks.
How does MAX_FPS interact with the --focus flag?
The --focus flag activates auto_fps_focus, which applies intelligent scene detection to concentrate frames on high-variance regions. However, both auto_fps and auto_fps_focus routes pass through _clamp_fps. Focused extraction redistributes the 2.0 fps budget temporally—it does not increase the rate. You get smarter frame placement, not more frames per second.
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 →