# How Claude-Video's Frame Budget Scales With Video Duration: A Technical Deep Dive

> Understand how Claude-Videos frame budget scales with video duration. Learn about the dynamic frame rate adjustment for efficient processing regardless of video length.

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

---

**Claude-Video uses a budget-aware algorithm that dynamically adjusts the extraction frame rate based on video length, ensuring the total frame count never exceeds a configurable maximum regardless of source duration.**

The `bradautomates/claude-video` repository implements an intelligent **frame budget** system that guarantees predictable processing costs across arbitrary video lengths. By combining hard caps with adaptive sampling, the tool extracts representative visual frames without overwhelming downstream processing pipelines. This analysis examines the exact source code mechanisms that govern how frame extraction scales from short clips to feature-length content.

## The Budget-Aware Algorithm

### Hard Caps and Configuration Constants

The frame budget system relies on two primary constants defined in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py):

- **MAX_FRAMES**: A hard ceiling (default ~300) that caps the total number of frames extracted from any video
- **DEFAULT_FPS**: The preferred extraction rate (typically 30 frames per second)

These values establish the boundaries within which the adaptive scaling operates.

### Video Duration Detection

Before calculating extraction parameters, the system determines the exact video length. In [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py), the code calls **ffprobe** with the `-show_entries format=duration` flag to retrieve the video's precise duration in seconds (`duration_secs`). This metadata retrieval happens during the download phase to inform subsequent processing decisions.

### Dynamic FPS Calculation

The core scaling logic resides in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py), which computes a **target frames-per-second** using the formula:

```

target_fps = min(DEFAULT_FPS, MAX_FRAMES / duration_secs)

```

This calculation produces two distinct behaviors:

- **For short videos**: When `MAX_FRAMES / duration_secs` exceeds `DEFAULT_FPS`, the system extracts at the default rate (e.g., 30 fps for a 10-second video yields 300 frames)
- **For long videos**: When the division yields a value below `DEFAULT_FPS`, the system samples at the reduced rate (e.g., a 300-second video extracts at 1 fps to stay within the 300-frame budget)

## Implementation in the Source Code

The extraction pipeline follows a strict sequence across three specialized files:

1. **[`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`
2. **[`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py)** provides the `MAX_FRAMES` and `DEFAULT_FPS` constants
3. **[`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py)** executes the calculation and constructs the ffmpeg command with the `-vf fps={target_fps}` filter

The ffmpeg filter transparently drops or duplicates frames to maintain the exact target rate, ensuring the final frame count never exceeds the configured budget.

## Practical Code Examples

The following Python implementation mirrors the actual logic found in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py):

```python
import subprocess
import json
import pathlib

def get_video_duration(path):
    """Mirror of download.py logic using ffprobe."""
    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, output_dir):
    """Implements the budget-aware extraction from frames.py."""
    MAX_FRAMES = 300      # From config.py

    DEFAULT_FPS = 30      # From config.py

    
    duration_secs = get_video_duration(video_path)
    
    # Dynamic scaling formula

    target_fps = min(DEFAULT_FPS, MAX_FRAMES / duration_secs)
    
    pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)
    
    # ffmpeg execution with computed fps filter

    subprocess.run([
        "ffmpeg", "-i", video_path,
        "-vf", f"fps={target_fps}",
        "-q:v", "2",
        f"{output_dir}/%05d.jpg"
    ], check=True)

```

For a 2-minute (120-second) video, the calculation would yield:

```python
duration_secs = 120
target_fps = min(30, 300 / 120)  # Returns 2.5 fps

# Total frames extracted: 120 * 2.5 = 300 (exactly at budget)

```

## Performance Characteristics

This scaling strategy ensures that **frame extraction time grows roughly linearly with video duration**, while the **number of output frames remains strictly bounded**. Because ffmpeg processes video sequentially, longer videos require proportionally more time to decode, but the output volume never exceeds `MAX_FRAMES`. This predictability prevents memory exhaustion and keeps downstream processing steps—such as captioning or Whisper transcription—within consistent computational bounds.

## Summary

- **Hard limits**: `MAX_FRAMES` (default ~300) in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py) sets an absolute ceiling on frame extraction
- **Adaptive sampling**: The formula `min(DEFAULT_FPS, MAX_FRAMES / duration_secs)` in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) dynamically adjusts the extraction rate
- **Duration detection**: [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) uses ffprobe to obtain precise video length before processing
- **Predictable output**: Frame counts remain bounded regardless of input duration, while processing time scales linearly with video length

## Frequently Asked Questions

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

According to the source code in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py), the system defines a `MAX_FRAMES` constant (default approximately 300) that serves as a hard cap. Regardless of video length or content, the extraction process will never generate more frames than this limit allows.

### How does Claude-Video calculate the frame extraction rate for long videos?

The calculation occurs in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) using the formula `target_fps = min(DEFAULT_FPS, MAX_FRAMES / duration_secs)`. For videos where the duration would produce more than `MAX_FRAMES` at the default rate, the system divides the frame budget by the video length to determine a reduced sampling rate, often dropping to 1 fps or lower for extended content.

### Does the frame extraction time increase with video duration?

Yes, extraction time grows roughly linearly with video duration because ffmpeg must sequentially decode the entire video stream. However, the **number of frames produced** remains constant due to the budget-aware algorithm, ensuring that downstream processing steps (like AI captioning) receive a consistent data volume regardless of input length.

### Where are the frame budget constants configured in the codebase?

The primary configuration values reside in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py), which exports `MAX_FRAMES` and `DEFAULT_FPS`. These constants are imported by [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) during the extraction workflow, allowing users to modify the budget limits by adjusting these configuration parameters.