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 videoDEFAULT_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_secsyields 30 fps or higher, so extraction proceeds at the fullDEFAULT_FPSof 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_FRAMESthreshold
Source Code Implementation
The scaling logic spans three key files in the skills/watch module:
skills/watch/scripts/download.py— Retrieves video metadata using ffprobe to determineduration_secsbefore extraction beginsskills/watch/scripts/frames.py— Implements the fps calculation formula and constructs the ffmpeg command with the-vf fps={target_fps}filterskills/watch/scripts/config.py— Houses the default configuration values includingMAX_FRAMESandDEFAULT_FPS
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_FRAMESconstant inskills/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, whileframes.pyorchestrates 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →