How Auto-FPS Calculation Works Based on Video Duration in Claude-Video
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, 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):
# 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
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:
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:
# 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:
# 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 to calculate extraction parameters programmatically:
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.pyto assign frame budgets ranging from 12 frames (short clips) tomax_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_focusapply 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. 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, specifically within the auto_fps and auto_fps_focus functions. The 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.
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 →