# How Auto-FPS Is Calculated for Different Video Durations in Claude-Video

> Discover how auto-fps is calculated in Claude-Video. Learn how frame budgets dynamically adapt to video length, ensuring optimal coverage while managing token costs.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: performance
- Published: 2026-08-07

---

**The `auto_fps` logic in `bradautomates/claude-video` assigns dynamic frame budgets based on video length, capping extraction at 2 FPS to balance visual coverage with token costs.**

The `watch` skill in the `bradautomates/claude-video` repository adaptively calculates frame rates to optimize Claude’s vision model usage. By varying the number of extracted frames according to duration, the tool ensures short clips receive dense sampling while long videos stay within token limits.

## Full-Video Frame Budgets (`auto_fps`)

For complete video scans, the `auto_fps` function in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) (lines 22-38) implements a tiered frame allocation strategy:

- **≤ 30 seconds**: Targets `max(12, round(duration))` frames, ensuring even brief clips capture at least 12 frames
- **30s < duration ≤ 60s**: Fixed target of 40 frames
- **1 minute < duration ≤ 3 minutes**: Fixed target of 60 frames
- **3 minutes < duration ≤ 10 minutes**: Fixed target of 80 frames
- **> 10 minutes**: Targets `max_frames` (default 100)

After calculating the raw frame count, the function divides by duration to derive the extraction FPS, then passes this value to `_clamp_fps` for enforcement of hard limits.

## Focused Range Density (`auto_fps_focus`)

When users specify a time range via `--start` and `--end` flags, the `auto_fps_focus` function (lines 41-60) applies denser sampling under the assumption that the selected segment requires higher detail:

- **≤ 5 seconds**: Uses `duration × 6` frames per second (aggressive sampling for brief moments)
- **5s < duration ≤ 15s**: Uses `duration × 4` frames, capped at `max_frames`
- **15s < duration ≤ 30s**: Fixed target of 60 frames
- **30s < duration ≤ 60s**: Fixed target of 80 frames
- **> 1 minute**: Targets `max_frames` (default 100)

This function is invoked in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) (lines 55-58) instead of `auto_fps` whenever a custom range is detected.

## Frame Rate Clamping and Safety Limits

Both calculation paths rely on the `_clamp_fps` helper (lines 49-53) which enforces two critical constraints:

1. **Maximum FPS**: Hard-capped at `MAX_FPS` (2.0) to prevent excessive token consumption per second of video
2. **Frame Budget**: The final target count never exceeds the supplied `max_frames` parameter

The clamping logic computes the target as `int(round(fps * duration))`, ensuring the actual extracted frame count respects both the duration-based target and absolute ceiling.

## Code Examples

Here is how the calculation behaves across different scenarios:

```python
from skills.watch.scripts.frames import auto_fps, auto_fps_focus

# Example 1: Full scan of a 45-second video

duration = 45.0
fps, target = auto_fps(duration)

# fps = 0.89 (40 frames / 45s), target = 40

print(f"fps={fps:.2f}, target={target}")

# Example 2: Focused 12-second segment

duration = 12.0
fps, target = auto_fps_focus(duration)

# fps = 2.0 (clamped from 4.0), target = 24 (12s × 2 FPS)

print(f"fps={fps:.2f}, target={target}")

# Example 3: 20-minute video with default max_frames=100

duration = 20 * 60
fps, target = auto_fps(duration)

# fps = 0.08, target = 100 (capped)

print(f"fps={fps:.2f}, target={target}")

```

## Summary

- **`auto_fps`** allocates 12–100 frames based on video length tiers, prioritizing higher density for short content
- **`auto_fps_focus`** multiplies frame budgets by 4×–6× for user-specified ranges, assuming detailed analysis is needed
- **`MAX_FPS`** (2.0) acts as a hard ceiling to control Claude vision API token costs
- **Implementation** resides in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py), with function selection logic in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py)

## Frequently Asked Questions

### What is the maximum frame rate the tool will ever use?

The absolute maximum is **2 FPS**, defined by the `MAX_FPS` constant in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py). Even if the duration-based calculation suggests a higher rate (e.g., 5 FPS for a focused 5-second clip), the `_clamp_fps` helper forces the value down to 2.0 to maintain predictable token costs.

### Why does focused range extraction use different logic than full-video?

Focused ranges assume the user has identified a specific moment requiring detailed inspection. Therefore, `auto_fps_focus` applies multipliers (4×–6×) that would be prohibitively expensive across an entire video but are acceptable for short segments. This approach balances coverage with cost only where precision matters most.

### How can I adjust the total number of frames extracted?

Modify the `max_frames` parameter passed to either function (default 100). In [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py), this value controls the upper bound for both `auto_fps` and `auto_fps_focus`, allowing you to increase density for high-detail analysis or decrease it for cost-sensitive processing of long content.

### What happens if a video exceeds 10 minutes?

Videos longer than 10 minutes automatically target the `max_frames` value (100 by default). The resulting FPS becomes approximately 0.08–0.17 depending on exact duration, ensuring the total token spend remains bounded regardless of input length.