Follow-up to the spatial crop dedup (#174). Cuts the dominant video GPU load.
Near-static videos are sampled into up to 64 frames, each re-running the whole detect→CCIP→SigLIP chain on ~identical content. Add a CPU perceptual-hash frame dedup upstream of the GPU so redundant frames are never processed at all (not just their embeds):
media.dedupe_frames() + _dhash(): 8×8 difference-hash (64-bit) per frame; greedy keep — a frame survives only if its hash differs from every kept frame by ≥ min_distance bits (Hamming). A static run collapses to one frame; distinct scenes all survive. Order + frame_time preserved.
Called in worker._download_decode right after sample_frames, so it runs in the decode stage on the downloader thread — GPU consumers only ever see deduped frames, and buffered video items shrink (less RAM).
Env-tunable FRAME_DEDUPE_DISTANCE (default 8; higher keeps more frames for brief localized changes an 8×8 hash can miss; 0 disables). Logs video frames N→M when it drops any.
This is the temporal axis complementing the per-frame spatial crop dedup. Build marker 2026-07-01.3. CI green on dev (run 1815); validated on the desktop after pull.
Follow-up to the spatial crop dedup (#174). Cuts the dominant video GPU load.
Near-static videos are sampled into up to 64 frames, each re-running the whole detect→CCIP→SigLIP chain on ~identical content. Add a **CPU perceptual-hash frame dedup upstream of the GPU** so redundant frames are never processed at all (not just their embeds):
- `media.dedupe_frames()` + `_dhash()`: 8×8 difference-hash (64-bit) per frame; greedy keep — a frame survives only if its hash differs from every kept frame by **≥ `min_distance`** bits (Hamming). A static run collapses to one frame; distinct scenes all survive. Order + `frame_time` preserved.
- Called in `worker._download_decode` right after `sample_frames`, so it runs in the **decode stage on the downloader thread** — GPU consumers only ever see deduped frames, and buffered video items shrink (less RAM).
- Env-tunable **`FRAME_DEDUPE_DISTANCE`** (default 8; higher keeps more frames for brief localized changes an 8×8 hash can miss; 0 disables). Logs `video frames N→M` when it drops any.
This is the temporal axis complementing the per-frame spatial crop dedup. Build marker `2026-07-01.3`. CI green on dev (run 1815); validated on the desktop after pull.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Near-static videos are the dominant GPU load: sampled into up to 64 frames, each
re-runs the whole detect→CCIP→SigLIP chain on ~identical content. Add a CPU
perceptual-hash frame dedup upstream of the GPU so the redundant frames are never
processed at all (not just their embeds).
- media.dedupe_frames() + _dhash(): 8×8 difference-hash (64-bit) per frame; greedy
keep — a frame survives only if its hash differs from every kept frame by
>= min_distance bits (Hamming). A static run collapses to one frame; genuinely
distinct scenes all survive. Order + frame_time preserved.
- Called in worker._download_decode right after sample_frames, so it runs in the
decode stage on the downloader thread (CPU) — the GPU consumers only ever see
deduped frames, and buffered video items shrink (less RAM too).
- Env-tunable FRAME_DEDUPE_DISTANCE (default 8; higher keeps more frames for brief
localized changes an 8×8 hash can miss; 0 disables). Logs `video frames N→M`
when it drops any, so video load reduction is visible.
Complements the spatial per-frame crop dedup (2026-07-01.2); this is the temporal
axis. Build marker 2026-07-01.3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up to the spatial crop dedup (#174). Cuts the dominant video GPU load.
Near-static videos are sampled into up to 64 frames, each re-running the whole detect→CCIP→SigLIP chain on ~identical content. Add a CPU perceptual-hash frame dedup upstream of the GPU so redundant frames are never processed at all (not just their embeds):
media.dedupe_frames()+_dhash(): 8×8 difference-hash (64-bit) per frame; greedy keep — a frame survives only if its hash differs from every kept frame by ≥min_distancebits (Hamming). A static run collapses to one frame; distinct scenes all survive. Order +frame_timepreserved.worker._download_decoderight aftersample_frames, so it runs in the decode stage on the downloader thread — GPU consumers only ever see deduped frames, and buffered video items shrink (less RAM).FRAME_DEDUPE_DISTANCE(default 8; higher keeps more frames for brief localized changes an 8×8 hash can miss; 0 disables). Logsvideo frames N→Mwhen it drops any.This is the temporal axis complementing the per-frame spatial crop dedup. Build marker
2026-07-01.3. CI green on dev (run 1815); validated on the desktop after pull.🤖 Generated with Claude Code