muvid.footage.align¶
Align a set of footage clips to the song — a thin wrapper over mixing.audio.
Each clip is a video file; its audio track (the different-device capture of the song) is
what we align. mixing.audio.align_clips_to_reference loads each clip’s audio via
pydub/ffmpeg (so a video path works directly — no separate extraction, no moviepy), and
returns offsets + a scale-invariant confidence + coverage clamped to the song timeline.
muvid does not estimate offsets itself — the estimator lives in mixing, which is
where the multi-device primitive and its measurements belong — but muvid is the one that
turns a measurement into a cut, so muvid is where “we are not sure” stops being a number
and becomes a refusal (muvid#59). The verdict that makes that possible is
vouches_for(), re-exported here beside the aligner that applies
it; it is defined in muvid.footage.edl, beside the record it judges and the gate
(validate_edl()) that enforces it.
Module Attributes
Analysis sample rate for alignment (mono). |
|
Estimator parameters |
Functions
|
Align |
|
Does the aligner vouch for this offset? The ONE place that verdict is reached. |
- muvid.footage.align.ALIGN_SAMPLE_RATE = 16000¶
Analysis sample rate for alignment (mono). 16 kHz is plenty for offset precision.
- muvid.footage.align.WINDOW_PARAMETERS = ('window_s', 'hop_s')¶
Estimator parameters
align_footage()refuses to forward, because changing them changes whatMIN_SUPPORTMEANS. Per mixing#43 (mixing PR #51), an explicitwindow_swider than a clip can hold a second, independent look at is refused bymixingitself with a typedWindowTooWideForClip, so that direction no longer reaches muvid as a silentsupport=None. (Where exactly that bound falls ismixing’s call to make and to change; muvid does not restate it here.) Narrowing the window is not caught by that refusal and still deflates every support — measured across eleven clip lengths, correct alignments read 0.38-0.70 at a 20 s window and 0.00-1.00 at a 4 s one — so correct alignments fall under the threshold instead. Refusing here regardless of whatmixingdoes about the wide-window case keeps the two packages from disagreeing about it later, and keeps the calibration decision (movingMUVID_FOOTAGE_MIN_SUPPORTif the window moves) something a person makes out loud rather than a side effect of a keyword — the refusal atmixing’s own entry point is a different failure mode for a different caller, not a substitute for muvid’s own gate.(Since
mixing>=0.0.48, passingwindow_salone also pairs it withhop = window/2, so the two are one knob at the estimator too. Another reason not to accept half of it through a keyword.)Refused rather than merely documented for the reason the rest of this package refuses things: an argument that quietly turns a safety check off is worse than one that is not accepted at all. Tuning the window is legitimate — it just has to move
MUVID_FOOTAGE_MIN_SUPPORTwith it, which is a decision someone has to make out loud rather than a side effect of a keyword.
- muvid.footage.align.align_footage(song_path, clips, *, song_duration=None, sample_rate=16000, **estimator_kwargs)[source]¶
Align
clips([(clip_id, clip_path), ...]) to the song atsong_path.Returns one
FootageAlignmentper clip, keyed byclip_id— including clips that do not overlap the song, which carryoverlaps=Falserather than being omitted, and clips the aligner could not vouch for, which carryreliable=Falserather than being omitted. Nothing may vanish from the record just because it matched badly; what a bad match loses is the right to be cut to silently (validate_edl()is where that is enforced).**A verdict already on disk is never re-judged, and re-aligning is how you re-judge it.** A
reliable=Truewritten by muvid 0.0.52 or earlier was reached against the UNGRADED support scale, where the muvid#59 shoot’s own correct offsets scored 0.42 and 0.46 — numbers the current threshold refuses. Those records keep their verdicts deliberately (from_dict()derives only an ABSENT verdict), because a stored verdict is a measurement someone’s project already depends on, not a value to reinterpret under a scale it never saw. Calling this function again is the supported way to get a verdict on today’s terms. Heavy deps (mixing.audio → numpy/scipy/pydub) are imported lazily here so importing the genre stays light.- Parameters:
song_path (
str) – The clean master every clip is aligned to.clips (
Sequence[tuple]) –(clip_id, clip_path)pairs; a video path works directly.song_duration (
float|None) – The song timeline length; probed fromsong_pathwhen omitted.sample_rate (
int) – Analysis sample rate (mono).**estimator_kwargs –
Passed straight to
mixing.audio.align_clips_to_reference— the seam for the windowed-consensus estimator’s parameters (muvid#59). Forwarding rather than enumerating keeps muvid out of the business of trackingmixing’s estimator vocabulary, and an argument the installedmixingdoes not accept raisesTypeErrorfrommixingnaming it. That failure is the point: a window parameter silently ignored is a caller believing they tuned an estimator that never saw the value.The window parameters are the exception and are REFUSED — see
WINDOW_PARAMETERS. They do not tune the estimator so much as re-scale the gate that reads it, and muvid refuses them at this entry point regardless of whethermixingitself would also refuse or silently answer.
- Return type:
- muvid.footage.align.vouches_for(*, confidence, support, margin=None, window_s=None)[source]¶
Does the aligner vouch for this offset? The ONE place that verdict is reached.
Lives here, beside the record it judges and the gate that enforces it, rather than with the aligner:
FootageAlignment.from_dict()has to reach it to derive a verdict for a record written before the field existed, and a module that owns a dataclass should not need its own consumer to interpret one.support(how much of the clip agrees) decides when the aligner measured it, because it is the only one of the two numbers that can tell a clear winner from a coin flip — seeFootageAlignment.support.**When support is absent, this falls back to
confidence, and that fallback is known to be inadequate.** It is the same instrument muvid#59 was filed about: on that shoot it would have refused two of the three wrong offsets and passed the third, which was 83 s out. So this is not “unknown forces approval” — an unmeasured support is judged by the weaker test rather than refused outright.The estimator fits its window to the clip and grades each window’s evidence, so a vote is held and is READABLE for almost everything —
support is Nonenow only for a clip too short to hold two windows at the 3 s floor (measured: 4 s yes, 6 s no). The support is used at whatever window it was measured at, which is a deliberate reversal: an earlier revision of this function refused to read a support from a fitted window, on the reasoning that an argmax headcount over few short windows is a weaker statistic than the same fraction at 20 s. That was true of the ungraded tally and is now actively wrong — see the note aboveMIN_SUPPORT. Measured on six pure-noise clips at a fitted 6.67 s window, the window guard vouches for FOUR of them by routing to the coefficient, while reading the graded support refuses all six.**Where it still falls back to the coefficient, it is guessing, and the measurements say so plainly.** On heavily degraded cross-device clips of the muvid#59 master, the worst CORRECT alignment scored 0.129 while the worst pure-noise clip scored 0.139 — the distributions overlap, so no threshold admits the correct ones and refuses the noise. Worse, the wrong offsets scored 0.183-0.252, higher than the correct ones. The real material agrees: of the three 10 s excerpts, the WRONG one carried the highest coefficient of the three (0.834 against 0.566 and 0.621).
So
MIN_CONFIDENCEwas deliberately NOT re-tuned. There is no value to tune it to: raising it past the noise floor refuses correct footage, and a number chosen to make a noise-floor test pass would hide that behind a green run. That fallback is now reached only by a clip too short to vote at all, which is the narrowest it has been.Two numbers, asking different questions, and BOTH are required.
MIN_SUPPORTasks whether enough of the clip’s evidence reached this offset;MIN_MARGINasks whether that evidence prefers this offset over every other one it considered. Neither subsumes the other, and the measurement that proves it is inMIN_SUPPORT’s note: margin alone scores 24/24 on real material where the support threshold scores 18/24, and then vouches for a bar-multiple REPEAT that the support threshold refuses. Aliases and noise fail differently; margin catches noise and only some aliases.So this is a strict tightening of what muvid 0.0.53 shipped — it can only refuse more, never less.
What muvid#91 becomes. Since the estimator fits its window down to a 3 s floor, the regime with no vote at all is now exactly clips shorter than
window_floor + hop— measured, 4.5 s: 4.4 s givessupport is Noneand 4.5 s is the first with a number. Those still fall back to the coefficient, which produces an inversion worth naming: a 4.4 s clip is VOUCHED while a 4.5 s one is refused, because falling off the bottom of the vote hands the decision to the weaker instrument. That is not defensible on its own terms, and it is left alone HERE only because changing it means separating a fresh verdict from a DERIVED one — a record predating these fields also hassupport is None, and refusing those would re-break what muvid#87 fixed. muvid#91 is now that specific decision, over a band too short to be usable music-video footage, rather than the open question about a third of a shoot that it started as.- Parameters:
confidence (
float) – The estimator’s correlation coefficient at the chosen lag.support (
float|None) – Graded fraction of window evidence reaching the offset, orNonewhen no vote could be held.margin (
float|None) – That tally minus the tally at the best offset outside the tolerance.Noneon exactly the same quorum assupport. Required to vouch when a vote WAS held: an aligner reporting support without it has not answered the separating question, and unknown does not vouch. Themixing>=0.0.51floor guarantees both, andtests/test_ci_extras_canary.pyasserts the capability so a mis-resolved floor fails loudly rather than quietly refusing every clip.window_s (
float|None) – The window support was measured at. Recorded and reported as a diagnostic; it does not enter the verdict, for the reason above.
- Return type:
- Returns:
True when the offset may be cut to without the caller opting in.