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

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. 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 invokes ffprobe to obtain the video’s precise duration in seconds (duration_secs). The core logic in 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:

When 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:

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:


# 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
  • 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, while 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. 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 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 stores the MAX_FRAMES and DEFAULT_FPS constants; download.py handles video duration detection via ffprobe; and frames.py implements the dynamic fps calculation and executes the ffmpeg extraction command.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →