How the Frame Cap Is Enforced After Deduplication in claude-video
The frame cap is enforced after deduplication by the _even_sample helper function, which evenly samples the deduplicated list down to the requested maximum while preserving the first and last frames.
The claude-video repository provides a watch skill that extracts representative frames from video files for AI analysis. After removing near-identical images through perceptual deduplication, the system must ensure the final set respects the user-defined frame cap. This article explains exactly how that limit is applied in the source code, referencing the specific functions and file paths in skills/watch/scripts/frames.py.
The Two-Stage Processing Pipeline
Frame extraction in the watch skill follows a strict sequence: generate candidates, deduplicate, then enforce the cap. This separation ensures that deduplication works on the full visual content before any trimming occurs, preventing premature deletion of unique frames that might be needed later.
The pipeline intentionally decouples deduplication from capping to maximize content diversity. If the cap were applied first, the system might eliminate important scenes before discovering they were duplicates, resulting in a sparse, unevenly distributed frame set.
Where Deduplication Ends and Capping Begins
The deduplication process runs via dedupe_perceptual, which compares frame fingerprints to remove near-identical images. However, this function operates independently of the max_frames parameter—it removes duplicates but does not count toward or enforce the user limit.
The cap is applied immediately afterward by calling _even_sample with the deduplicated list and the target count. This pattern appears consistently across all three extraction engines in skills/watch/scripts/frames.py.
Scene and Uniform Extraction Paths
In the scene detection engine (extract_scene_or_uniform), the code explicitly separates these two stages:
deduped, n_dropped = dedupe_perceptual(scene_frames) if dedup else (scene_frames, 0)
cap = len(deduped) if max_frames is None else max_frames # ← cap decision
selected = _even_sample(deduped, cap) # ← enforce cap
These operations occur at lines 443–452 in skills/watch/scripts/frames.py. The cap variable resolves to either the full length of the deduplicated list (if no limit was specified) or the max_frames value provided by the user. The _even_sample function then performs the actual reduction.
Key-Frame Extraction Path
The key-frame engine follows an identical pattern in extract_keyframes at lines 672–679:
deduped, n_dropped = dedupe_perceptual(candidates) if dedup else (candidates, 0)
cap = len(deduped) if max_frames is None else max_frames
selected = _even_sample(deduped, cap)
Whether the system uses scene detection, key-frame extraction, or the uniform fallback path, the architecture remains consistent: deduplicate first, then invoke _even_sample to enforce the limit.
Inside the _even_sample Algorithm
The _even_sample function (lines 994–1007 in skills/watch/scripts/frames.py) handles the final enforcement logic through three distinct operations.
Even Index Calculation
First, the function computes target indices using an internal _even_indices(count, n) helper. This generates n evenly spaced indices across the full range of deduplicated frames, mathematically guaranteeing that the first (index 0) and last (index count-1) frames are always retained. This preserves temporal boundaries while distributing the remaining selections uniformly.
File System Cleanup
After determining which indices to keep, _even_sample deletes the physical JPEG files associated with the discarded indices. This cleanup ensures the output directory contains only the final, capped frame set, preventing storage bloat from intermediate files that exceeded the limit.
Contiguous Re-indexing
Finally, the surviving frames are re-indexed to a contiguous 0..n-1 range. This normalization ensures downstream consumers receive a clean, predictable sequence regardless of how many frames were removed during deduplication or capping.
Practical Implementation Examples
When calling the extraction functions in claude-video, the max_frames parameter controls the post-dedup cap:
# Example: extract up to 50 frames, with deduplication
from pathlib import Path
from skills.watch.scripts.frames import extract_keyframes
frames, meta = extract_keyframes(
video_path="demo.mp4",
out_dir=Path("out"),
max_frames=50, # <-- desired cap
dedup=True,
)
# `frames` now contains at most 50 entries, even-sampled after deduplication.
For scene-based extraction with the same enforcement:
from skills.watch.scripts.frames import extract_scene_or_uniform
selected, meta = extract_scene_or_uniform(
video_path="lecture.mp4",
out_dir=Path("out"),
fps=2.0,
target_frames=80, # <-- cap before dedup
max_frames=80,
dedup=True,
)
# `selected` respects the 80-frame limit after deduplication.
Summary
- Deduplication happens first:
dedupe_perceptualremoves near-identical frames without considering themax_frameslimit. - The cap is applied second:
_even_sampleis called immediately after deduplication in bothextract_scene_or_uniformandextract_keyframes. - Even sampling preserves boundaries: The algorithm always retains the first and last frames while distributing selections evenly across the remaining temporal range.
- Physical cleanup occurs: Unselected frame files are deleted from disk, and survivors are re-indexed to a contiguous sequence.
- Consistent across engines: Whether using scene detection, key-frame extraction, or uniform sampling, the post-dedup capping logic remains identical in
skills/watch/scripts/frames.py.
Frequently Asked Questions
Does deduplication happen before or after the frame cap is applied?
Deduplication happens before the frame cap is applied. The dedupe_perceptual function processes the full candidate list to remove visual duplicates, then _even_sample enforces the max_frames limit on the resulting deduplicated set. This order ensures that unique frames are not prematurely discarded due to an initial cap that doesn't account for redundancy.
What happens to the JPEG files of frames that exceed the cap?
The _even_sample function physically deletes the JPEG files for any frames that are not selected during the capping process. After computing the evenly spaced indices to retain, it removes the files at discarded indices from the output directory, ensuring only the capped frame set remains on disk.
How does _even_sample decide which frames to keep?
_even_sample uses an internal _even_indices helper to calculate mathematically even spacing across the available frames. It always includes the first and last frames of the deduplicated list, then selects additional frames at regular intervals to reach the requested count. This guarantees temporal coverage from start to finish while respecting the maximum limit.
Is the frame cap enforced differently for scene detection versus key-frame extraction?
No, the frame cap enforcement is identical across extraction methods. Both extract_scene_or_uniform (lines 443–452) and extract_keyframes (lines 672–679) use the same three-step pattern: deduplicate, calculate the cap value, then call _even_sample. The uniform fallback path also follows this same implementation in skills/watch/scripts/frames.py.
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 →