The release that follows your athlete through the whole game, and stops suggesting moments they were never in.
Your athlete, past the fragment you pointed at
Identifying a child only ever labelled them where you happened to look. On a real game that left an athlete known for 31.7s of 300s across six fragments — all inside the one 32-second window originally clicked. Every signal that follows the athlete was dark for the other 90%, and the moments that survived were scene-wide ones with nothing to do with them.
A jersey is the one thing about a child a detector can see that stays the same all afternoon. The CV worker now takes an appearance pass: a coarse HSV histogram of the torso, read from the 540p proxy in one pass.
Colour is a veto, not an identifier, and that is the whole design. Measured against the production game three ways:
| rule | result |
|---|---|
| colour only (≥ 0.55) | 661 of 1152 tracks — 2306s of "athlete" in a 300s video |
| continuity only | 56 tracks, 120.3s |
| both | 14 tracks, 51.2s (up from 6 tracks, 31.7s) |
Teammates wear the same shirt, so colour alone selects a team — and the children it wrongly volunteers are exactly the ones standing next to yours. Continuity alone links whoever happens to be nearby. So the identity claim rests on continuity — a fragment beginning where and when another ended, within 2s and a distance a child could actually run — with colour able only to rule a link out.
Nothing is assigned automatically. Matches are pre-selected in the picker with the evidence behind each one — the gap, the distance, the colour agreement — and a human confirms. The cost of a confident wrong answer is another family's child in your highlight reel.
A moment your athlete is not in is not your athlete's moment
Production, with everything else working: seven suggested moments, of which five contained no trace of the child they were supposedly of. He was on screen from 218s; the moments were at 49s, 68s, 158s, 175s and 182s. Every one was a real scramble under the rim, and every one was somebody else's kid.
Two of the seven signals — activity_near_goal and high_motion — read the whole scene and never look at the athlete. Between them they carried 0.25 of weight against a 0.35 threshold, enough to clear it unaided. The scorer was answering "was anything happening?" when the question is "was anything happening to him?"
Once you have said which child is yours, a window they are not in scores zero. Scene signals still contribute — a scramble the athlete is in is exactly what to keep — they simply cannot carry a window alone. With no athlete identified, nothing changes.
before 7 moments, 5 of them with no athlete in frame
after 2 moments, both of them him
Four reasons a five-minute game suggested nothing
1,415 tracks, a rim seen for 28s, a ball for 23s, and every line the user saw reading plausibly. Together they said the footage was dull. The footage was fine — the athlete every focal signal depends on was bound to a ten-frame fragment lasting 0.3s of 300s, and nothing on screen said so.
- Absent is not idle. Focal signals returned 0 rather than null when the athlete had no position, keeping 0.35 of weight in every denominator and reporting a ceiling of 1.000 that was arithmetically unreachable.
- Say how much of the game the athlete is actually on screen for. A binding covering under 5% of the footage now names itself as the likely reason, instead of "athlete identified: yes" implying otherwise.
- Re-identification could only shrink an athlete. Matching took the single best new track per old track, so the 0.3s binding survived two re-detections intact.
- Do not detect from a proxy smaller than the detection size. The 540p editing proxy was being upscaled — identical inference cost for strictly less picture. Same preset, same game: 145,975 detections across 3,948 tracks from the source, against 67,985 across 1,415 from the proxy. The ball goes first.
An announcer over the reel
Per-moment titles with AI-written lines, spoken by ElevenLabs and mixed over the game. One request writes every line at once, so the reel reads as a single broadcast rather than four disconnected sentences.
It never claims a basket, a steal, or a score, because nothing in this system knows any of those — a line about a shot that missed is worse than silence to someone who was in the gym. Everything degrades rather than fails: no key means templates, a refusal means templates, a line that will not synthesise is skipped. Speech is cached by content hash, so re-rendering after changing one clip does not re-pay for the rest.
A front door
reeleel.com redirected straight to /login. A site whose only public page is a password prompt tells a visitor nothing about what it is. There is now a landing page, with the palette sampled from the mascot rather than invented, and no webfont — nothing on the page makes a network request.
It states plainly what the product cannot do: it cannot know whether a shot went in, read a scoreboard, or tell you who won. That is the most useful thing on the page.
Fixes worth naming
- Every clip rendered pure black.
-sswas an output option, so FFmpeg filtered from 0:00 and handed the graph frames stamped past the fade-out's end. Measured YAVG 16 — pure black — against 123 with the fade removed. Clips rendered before this fix are still black on disk and need regenerating. - The review page could not be played. The box canvas covered the play button: "i can't click play i just have cross hairs". Identifying is now an explicit mode, and the canvas is transparent to the pointer.
- A real logo at the size it is displayed. The mark was generated at 96px and shown at 148, so the browser was upscaling it. The placeholder teal square that was standing in for the mascot on a live site is deleted outright.
- The footer no longer claims your footage stays on your own server. True only when self-hosting, and the landing page is read by people who are not.
Known limits
- The COCO model cannot see a hoop. A basketball-specific model is on the server, selected by a global environment variable rather than a per-project choice.
- Nothing extracts audio, so the
audio_spikesignal has never fired. - Every deploy kills a running analysis.
- Stitching raises coverage from 31.7s to 51.2s of a 300s game — better, not solved. A child who leaves frame entirely and returns in different light is still two athletes as far as the colour veto is concerned.