# How Auto-FPS Calculation Works Based on Video Duration in Claude-Video

> Discover how Claude-Video calculates auto-fps using duration buckets and converts targets into concrete fps values up to 2.0. Optimize your video processing today.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: deep-dive
- Published: 2026-08-06

---

**The auto-fps calculation selects a frame rate by first assigning a target frame budget based on duration buckets, then converting that target into a concrete fps value capped at 2.0 frames per second.**

The `bradautomates/claude-video` repository implements intelligent frame extraction to optimize token costs while preserving visual detail. Located in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py), the auto-fps calculation automatically scales frame extraction rates according to video length, ensuring short clips remain detail-rich while long videos stay economically viable.

## Duration-Based Frame Budgeting

The core logic resides in the `auto_fps` function, which partitions videos into duration buckets and assigns a **target frame count** for each. This target represents the desired number of frames to extract before final clamping adjustments.

### Short Videos (30 Seconds or Less)

For videos under 30 seconds, the algorithm calculates a minimum of 12 frames while aiming for approximately one frame per second, capped by the user-defined `max_frames` parameter (default 100):

```python

# skills/watch/scripts/frames.py#L122-L138

if duration_seconds <= 30:
    target = min(max_frames, max(12, int(round(duration_seconds))))

```

A 20-second video receives a target of 20 frames, while a 5-second clip receives the 12-frame minimum guarantee.

### Medium Videos (30 Seconds to 10 Minutes)

Longer content receives progressively larger but sub-linear frame budgets to control costs:

- **30–60 seconds**: Fixed target of 40 frames
- **1–3 minutes**: Fixed target of 60 frames  
- **3–10 minutes**: Fixed target of 80 frames

```python
elif duration_seconds <= 60:
    target = min(max_frames, 40)
elif duration_seconds <= 180:
    target = min(max_frames, 60)
elif duration_seconds <= 600:
    target = min(max_frames, 80)

```

### Long Videos (Over 10 Minutes)

Videos exceeding 600 seconds bypass bucket calculations and use the maximum allowable frame count directly:

```python
else:
    target = max_frames

```

## FPS Calculation and Hard Ceiling

After determining the target frame count, the system converts it to a frames-per-second value and applies a hard ceiling. The `MAX_FPS` constant limits extraction to **2.0 fps** regardless of calculated density:

```python

# skills/watch/scripts/frames.py#L49-L53

fps = min(fps, MAX_FPS)                     # never exceed 2 fps

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

```

This two-step process ensures that even very short videos requesting high temporal density get clamped to 2 fps, while the final frame count is recalculated to match the constrained rate.

## Focused Range Extraction with auto_fps_focus

When users specify a start/end window for detailed analysis, the `auto_fps_focus` function applies an aggressive budgeting strategy with higher multipliers for short segments:

```python

# skills/watch/scripts/frames.py#L141-L158

if duration_seconds <= 5:
    target = min(max_frames, max(10, int(round(duration_seconds * 6))))
elif duration_seconds <= 15:
    target = min(max_frames, max(30, int(round(duration_seconds * 4))))
elif duration_seconds <= 30:
    target = min(max_frames, 60)
elif duration_seconds <= 60:
    target = min(max_frames, 80)
elif duration_seconds <= 180:
    target = max_frames
else:
    target = max_frames

```

Focused segments under 5 seconds receive up to 6 frames per second (before clamping), ensuring detailed sections capture rapid motion or transitions.

## Practical Code Examples

Import the functions from [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) to calculate extraction parameters programmatically:

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

# 20-second clip (no focus)

fps, frames = auto_fps(20.0)
print(fps, frames)  # 2.0 40

# 45-second clip (no focus)  

fps, frames = auto_fps(45.0)
print(fps, frames)  # 0.89 40

# 4-second focused segment

fps, frames = auto_fps_focus(4.0)
print(fps, frames)  # 2.0 8 (2 fps × 4s = 8 frames after clamping)

```

The calculations respect the `max_frames` constraint throughout, ensuring the final output never exceeds the user-defined budget regardless of duration multipliers.

## Summary

- The auto-fps calculation uses duration buckets in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) to assign frame budgets ranging from 12 frames (short clips) to `max_frames` (long videos).
- **Short videos** (≤30s) receive approximately one frame per second with a 12-frame minimum.
- **Medium videos** (30s–10min) receive fixed allocations (40, 60, or 80 frames) to balance detail and cost.
- A **hard ceiling of 2.0 fps** (`MAX_FPS`) ensures extraction rates never exceed this limit, recalculating the final frame count accordingly.
- **Focused ranges** via `auto_fps_focus` apply higher density multipliers (up to 6×) for user-specified time windows.

## Frequently Asked Questions

### What is the maximum fps allowed in the auto-fps calculation?

The system enforces a hard limit of **2.0 fps** through the `MAX_FPS` constant defined in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py). Even if the duration-based calculations suggest a higher rate, the `min(fps, MAX_FPS)` clamp ensures extraction never exceeds two frames per second.

### How does auto_fps_focus differ from the standard auto_fps?

`auto_fps_focus` applies to user-specified time ranges and uses more aggressive multipliers—up to 6× duration for segments under 5 seconds—while `auto_fps` uses conservative linear or fixed budgets. Both functions ultimately respect the 2.0 fps ceiling and `max_frames` limit, but focused mode prioritizes temporal density for short analysis windows.

### Where is the auto-fps logic implemented?

The primary implementation resides in **[`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py)**, specifically within the `auto_fps` and `auto_fps_focus` functions. The [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) module orchestrates the extraction pipeline and invokes these functions when processing video content.

### Why does the calculation use duration buckets instead of a linear formula?

Bucket-based allocation prevents excessive frame counts on long content while guaranteeing minimum detail on short clips. This tiered approach optimizes token costs for the Claude Video API, ensuring that a 10-minute video does not generate 600 frames (which would occur with a simple 1 fps linear rate), while still capturing at least 12 frames from a 5-second clip.