# How Frame Budget Scales With Video Duration in Claude Video: A Technical Deep Dive

> Discover how Claude Video's frame budget scales with video duration using its budget-aware algorithm. Learn how this ensures predictable processing times for all video lengths.

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

---

**Claude-Video employs a budget-aware extraction algorithm that dynamically calculates the target frame rate based on video length to enforce a hard cap of approximately 300 frames, ensuring predictable processing times across videos of any duration.**

The Claude-Video open-source project provides intelligent video frame extraction that balances visual representation with computational efficiency. Understanding how the frame budget scales with different video durations is essential for optimizing processing pipelines and predicting resource usage when working with the `bradautomates/claude-video` repository.

## The Frame Budget Algorithm

Claude-Video implements a **budget-aware extraction strategy** that guarantees the total number of extracted frames never exceeds a predefined threshold, regardless of how long the input video runs. This approach prevents memory exhaustion and keeps downstream processing steps (such as captioning or transcription) computationally feasible.

### Hard Cap Configuration

The system defines its constraints in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py). Two constants govern the extraction behavior:

- **`MAX_FRAMES`** (default ≈ **300**) — The absolute upper limit on the total number of frames the extractor will ever generate from a single video
- **`DEFAULT_FPS`** (default **30**) — The preferred frames-per-second extraction rate for videos that fit comfortably within the budget

These values create a predictable boundary: even if you process a 10-hour video, the extractor will never output more than approximately 300 frames.

### Dynamic FPS Calculation

Before extraction begins, [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) invokes **ffprobe** to obtain the video’s precise duration in seconds (`duration_secs`). The core logic in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) then computes the extraction rate using the formula:

\[
\text{target\_fps} = \min(\text{DEFAULT\_FPS},\; \frac{\text{MAX\_FRAMES}}{\text{duration\_secs}})
\]

This calculation ensures:
- **Short videos** (e.g., 10 seconds): `MAX_FRAMES / duration_secs` yields 30 fps or higher, so extraction proceeds at the full `DEFAULT_FPS` of 30 frames per second
- **Long videos** (e.g., 5 minutes / 300 seconds): The division drops to 1 fps, forcing the extractor to sample fewer frames per second while maintaining comprehensive visual coverage
- **Very long videos**: The fps approaches zero asymptotically, capping the total output at the `MAX_FRAMES` threshold

## Source Code Implementation

The scaling logic spans three key files in the `skills/watch` module:

- **[`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py)** — Retrieves video metadata using ffprobe to determine `duration_secs` before extraction begins
- **[`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py)** — Implements the fps calculation formula and constructs the ffmpeg command with the `-vf fps={target_fps}` filter
- **[`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py)** — Houses the default configuration values including `MAX_FRAMES` and `DEFAULT_FPS`

When [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py) executes, it passes the computed `target_fps` to ffmpeg’s fps video filter. This filter transparently drops or duplicates frames as needed, ensuring the final output count never exceeds the budget while maintaining evenly spaced temporal sampling throughout the video duration.

## Practical Code Examples

The following Python implementation mirrors the behavior of the Claude-Video skill:

```python
import subprocess
import json
import pathlib

def get_video_duration(path: str) -> float:
    """Extract duration using ffprobe (as implemented in download.py)."""
    cmd = [
        "ffprobe", "-v", "error",
        "-show_entries", "format=duration",
        "-of", "json", path
    ]
    output = subprocess.check_output(cmd)
    return float(json.loads(output)["format"]["duration"])

def extract_frames_with_budget(video_path: str, output_dir: str):
    """Extract frames respecting the MAX_FRAMES budget."""
    # Configuration constants from config.py

    MAX_FRAMES = 300
    DEFAULT_FPS = 30
    
    # Calculate dynamic fps based on duration

    duration = get_video_duration(video_path)
    target_fps = min(DEFAULT_FPS, MAX_FRAMES / duration)
    
    # Prepare output directory

    pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)
    
    # Execute ffmpeg with calculated fps (as in frames.py)

    subprocess.run([
        "ffmpeg", "-i", video_path,
        "-vf", f"fps={target_fps}",
        "-q:v", "2",
        f"{output_dir}/%05d.jpg"
    ], check=True)
    
    print(f"Extracted at {target_fps:.2f} fps to stay within {MAX_FRAMES} frame budget")

```

For command-line usage, you can observe the automatic scaling by processing videos of different lengths:

```bash

# Process a short clip (will extract at full 30 fps)

python -m skills.watch.scripts.frames short_clip.mp4 ./output/

# Process a long lecture (automatically reduces to ~1 fps or lower)

python -m skills.watch.scripts.frames lecture_60min.mp4 ./output/

```

## Summary

- Claude-Video enforces a **hard frame budget** of approximately 300 frames per video via the `MAX_FRAMES` constant in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py)
- The system **calculates target fps** using `min(DEFAULT_FPS, MAX_FRAMES / duration_secs)`, ensuring the frame count scales inversely with video duration
- **ffprobe** detects video length in [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py), while [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py) orchestrates the ffmpeg extraction with the computed frame rate
- This budget-aware approach guarantees that **processing time and memory usage remain predictable** regardless of input video length, from 10-second clips to multi-hour recordings

## Frequently Asked Questions

### What is the maximum number of frames Claude-Video will extract from a single video?

Claude-Video caps extraction at approximately **300 frames** by default, defined by the `MAX_FRAMES` constant in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py). Even if you process a video several hours long, the budget-aware algorithm will automatically reduce the extraction frame rate to ensure this limit is never exceeded.

### How does Claude-Video handle very short videos under 10 seconds?

For short videos where `MAX_FRAMES / duration_secs` exceeds the `DEFAULT_FPS` value (typically 30 fps), the system extracts frames at the full default rate. A 10-second video would generate approximately 300 frames at 30 fps, utilizing the entire budget to provide maximum visual detail for brief content.

### What happens if a video exceeds the frame budget?

The video does not get rejected. Instead, Claude-Video **automatically reduces the extraction frame rate** proportionally to the video length. The `target_fps` calculation in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) ensures that longer videos are sampled at lower frequencies (potentially 1 fps or lower), maintaining representative coverage while respecting the hard cap.

### Which files control the frame extraction parameters?

The extraction parameters are governed by three files in the `skills/watch/scripts/` directory: **[`config.py`](https://github.com/bradautomates/claude-video/blob/main/config.py)** stores the `MAX_FRAMES` and `DEFAULT_FPS` constants; **[`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py)** handles video duration detection via ffprobe; and **[`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py)** implements the dynamic fps calculation and executes the ffmpeg extraction command.