This is the analyzer: pick a clip and Shuttler walks you through six guided steps — verify the court, run the pipeline, and read the Insight Report. Clips are read locally by path — nothing is uploaded.
The app auto-detects the court and proposes the markings. In the tapper below, Load video (pick the same clip) and the proposal appears in Court mode. Drag any marking that sits off the painted lines — the loupe shows the exact pixel, same precision as tapping — and add/delete points as needed, then Export (it saves straight to the app). If auto couldn't lock on (busy/multi-court footage), you start blank and tap ≥4 line-intersections yourself. Either way you verify before running.
Two courts are drawn on your reference frame: green = the court your raw taps imply, amber = the refined fit snapped to the real painted lines; ✕ = your taps. Where green and amber diverge, refinement had to pull the court off your taps to reach the paint — a sign those taps are off. Both should sit on the painted lines before the minutes-long run.
Calibrating…
Calibrate → shuttle → segment → classify → score → render. Minutes of local compute.
the shareable, honesty-led summary — rallies, tempo, movement, and what one camera can’t call
to measure these calls against what actually happened
Loading player movement…
Loading rally tempo…
Renders one rally: detected shuttle + player movement + honest scoring.
Seed the pipeline's own rally calls as editable rows, then correct what's
wrong and add the rallies it missed — far faster than marking from scratch. Or scrub and mark
by hand. Each row is tagged pipeline or human;
correcting a pipeline row flips it to human. This writes the ground-truth
<clip>.rallies.json the eval harness scores against — it does not change a run.
Can't call a rally? Leave winner/how blank — an honest abstention is valid ground truth.
(This GT lets us measure accuracy beyond the one annotated clip and tune the abstain
threshold; it doesn't itself lift what the pipeline can see.)