muvid.footage.scoring.frames¶
One decode pass per clip → the shared per-frame artifacts the quality + motion extractors both consume.
The design review flagged that quality.py and motionbeat.py must NOT each decode the clip and
each estimate camera motion — that doubles IO/CPU on the memory-fragile box and makes the
“camera-motion computed once” claim false. So a single sequential sample_clip_frames()
pass computes, per sampled frame: sharpness, exposure, an (injected) face score, the
camera-compensated motion residual, and the global-motion (shake) magnitude — in clip time.
The orchestrator maps clip time → song time via the clip’s offset and hands this
FramePass to both extractors.
cv2 is lazy-imported (muvid[scoring] extra). Hard caps (max_frames) bound the work;
should_cancel is polled so a cancel lands within a few frames.
Module Attributes
Default frame sample rate (Hz) — plenty for quality + a motion envelope onto a 10 Hz grid. |
|
Default hard cap on sampled frames per clip (bounds CPU + memory regardless of duration). |
Functions
Build a |
|
|
Decode |
Classes
|
Per-sampled-frame metrics for one clip, in CLIP time (seconds from the clip start). |
- muvid.footage.scoring.frames.DEFAULT_MAX_FRAMES = 1200¶
Default hard cap on sampled frames per clip (bounds CPU + memory regardless of duration).
- muvid.footage.scoring.frames.DEFAULT_SAMPLE_FPS = 5.0¶
Default frame sample rate (Hz) — plenty for quality + a motion envelope onto a 10 Hz grid.
- class muvid.footage.scoring.frames.FramePass(clip_times, sharpness, exposure, face, motion_residual, global_dx, global_dy, fps, n_sampled)[source]¶
Bases:
objectPer-sampled-frame metrics for one clip, in CLIP time (seconds from the clip start).
- muvid.footage.scoring.frames.make_face_scorer()[source]¶
Build a
bgr_frame -> face_framing_score | None(orNoneif unavailable).Best-effort and never fatal: face_framing is a soft metric (not one of the two named signals), so ANY failure →
Noneand the metric reads as unmeasured (NaN → masked → not counted in the composite denominator), never as a zero score. Tries the classicmp.solutions.face_detection(mediapipe 0.10 full build); falls back to the TasksFaceDetectorONLY when the operator supplies a model viaMUVID_MEDIAPIPE_FACE_MODEL(no auto-download). Score = best face’s area×centering.
- muvid.footage.scoring.frames.sample_clip_frames(clip_path, *, sample_fps=5.0, max_frames=1200, face_fn=None, flow_downscale=4, should_cancel=None)[source]¶
Decode
clip_pathONCE, sampling ~``sample_fps`` frames → aFramePass.- Parameters:
clip_path (
str) – the video file.sample_fps (
float) – target frames/second to analyze (strided over the native fps).max_frames (
int) – hard cap on analyzed frames (bounds cost).face_fn (
Optional[Callable[[ndarray],float]]) – optionalbgr_frame -> face_score | None(mediapipe, injected by the caller so this module stays cv2-only).None→ face score is NaN everywhere, i.e. not measured rather than measured as worst.flow_downscale (
int) – downscale factor for the Farneback flow (cost bound).should_cancel (
Optional[Callable[[],bool]]) – polled every frame; returns early (a partial pass) when it goes True.
- Return type: