muvid.mcp.scoring_tools

MCP tools for the footage SCORING layer (thorwhalen/muvid#13).

A background scoring job (via nw.jobs — the federation’s durable/cancellable async facade, reused rather than a second system) computes per-clip score tracks; the editor + assemble_music_video(strategy='weighted') read them. All FREE (no AI/keys).

A transport over muvid.footage.service (require_scorable, run_scoring, scores): what stays here is the connector’s own job — enqueueing on nw.jobs and the bounded long-poll over it. A host runs the same score operation as its own job.

Key design decisions (LOCKED, see misc/docs/footage_scoring_design.md):

  • Scoring is keyed on INPUTS ONLY (song_hash + an alignment fingerprint + the metric set + hop). Weights/preset are NOT here — they enter at assemble time, so ONE tensor is reused across every preset for free, and a re-align mid-flight yields a NEW job (not a dedup to the stale run).

  • Bounded long-poll status so an agent needs ~1 poll, not ~15.

  • NaN never hits the wire — masked entries serialize as null; the mask array is authoritative.

Functions

footage_score_status(project_id, *[, ...])

The scoring job's status (bounded long-poll).

footage_scores(project_id, *[, clip_id, ...])

The persisted score tracks — for the multichannel editor + inspection.

score_footage(project_id, *[, hop_s, metrics])

Kick a BACKGROUND job that scores every aligned clip (quality + motion-to-beat).

muvid.mcp.scoring_tools.footage_score_status(project_id, *, job_id='', wait_s=0)[source]

The scoring job’s status (bounded long-poll). Free.

Pass the job_id from score_footage (or omit for the newest scoring job). With wait_s > 0 this blocks up to ~``wait_s`` seconds (capped), returning early on a terminal state — so an agent needs ~1 poll, not many.

Return type:

dict

muvid.mcp.scoring_tools.footage_scores(project_id, *, clip_id='', metrics=None, max_points=1500)[source]

The persisted score tracks — for the multichannel editor + inspection. Free.

  • No clip_id → a SUMMARY (metrics, per-clip coverage %, beats, tempo, the decimated selection_margin, grid geometry) — bounded, safe as the default.

  • clip_id → that clip’s tracks (values as null-masked arrays, decimated to max_points per metric), for the editor’s lanes.

Return type:

dict

muvid.mcp.scoring_tools.score_footage(project_id, *, hop_s=0.1, metrics=None)[source]

Kick a BACKGROUND job that scores every aligned clip (quality + motion-to-beat). Free.

Returns immediately with a job_id; poll footage_score_status. Scoring extracts ALL core metrics (re-weight later at assemble time — no re-scoring needed). Requires a song + a run of align_footage first. The heavy lip-sync tier is OFF by default (opt-in, off-prod).

Return type:

dict