cue.pruner¶
In-process keyframe pruner.
Runs inside the cue.ocap_launcher subprocess. ocap's GStreamer pipeline is
patched to tee a downsampled video branch into an appsink, and each new
sample fires process_frame() below. The pruner keeps a frame only when
its dhash differs enough from the previous keeper's — we deliberately
ignore keyboard / mouse / window events here, since those are already
recorded verbatim in MCAP and the digest prompt receives them as text.
The job of this module is to drop frames that carry no visual change
worth sending to Haiku.
Public API
process_frame(bgra_bytes, width, height, ts_ns) # per-frame hook recent_keyframes(recent_secs, limit=5) evict_older_than(cutoff_ns) evict_keeping_newest(keep_count) clear_state()
recent_keyframes ¶
recent_keyframes(recent_secs: float, limit: int = 5) -> list[Path]
The limit most recent keyframe JPEGs within recent_secs, newest first.
evict_newer_than ¶
evict_newer_than(cutoff_ns: int) -> int
Delete keyframes whose filename timestamp is >= cutoff_ns (inclusive).
Used by the privacy-pause purge path: when pause fires, anything captured
at or after cutoff_ns is considered potentially-sensitive and removed.
Inclusive >= is intentional — a frame whose ts exactly matches cutoff
may still carry sensitive bytes and an extra delete is trivial.
evict_keeping_newest ¶
evict_keeping_newest(keep_count: int) -> int
Keep only the keep_count newest keyframes; delete the rest.
Called from digest.py after each digest run so keyframes don't accumulate without bound. Returns count evicted.
clear_state ¶
clear_state() -> None
Reset in-memory pruner state. Used when the recorder toggles off.
process_frame ¶
process_frame(bgra_bytes: bytes, width: int, height: int, ts_ns: int) -> bool
Evaluate a single frame. Save a JPEG if it qualifies as a keyframe. Returns True if the frame was kept. Intended to be called from the ocap subprocess's pipeline appsink callback.
dhash ¶
dhash(img) -> int
64-bit perceptual hash: 9×8 grayscale, adjacent-column gradient.
Intentionally coarse — a single keystroke is smoothed out by the
resize, which matches pruner's purpose of catching only layout-level
changes. Public utility: also used by cue.frame_select for
near-duplicate detection.