
We’re approaching World Cup season - I've been losing sleep to stressful penalty shootouts, and this little stress ball has been sitting on my desk the whole time. At some point the two facts collided: the most agonising moments of this tournament can come down to did the ball cross the line or not — the exact thing goal-line technology and VAR exist to settle. So I thought: could I build my own scrappy version of that and run it on the edge?
In all fairness, this was really just an excuse to get my hands dirty with the Voyager SDK end-to-end - but a penalty shootout in my living room is a much better motivator than some benchmarks. 😅
The match setup.
The official match ball is the Axelera stress ball. The goalposts are… two plants in mugs. I roll the ball at the goal, and the system calls GOAL or MISS — and crucially, rebounds off the wall behind don't count, because the ball has to actually cross the line. I don't detect the goal itself; I just eyeball one frame and click where the posts are to draw the line:

How it works
Three simple layers:
- Detection: a stock COCO
yolo26smodel runs on the AIPU and finds the ball (it shows up as COCO's "sports ball" class - thankfully no custom training needed). - Tracking: I follow the ball's centre across frames and bridge the gaps when detection blinks out on a fast, blurry shot. For a single ball, nearest-point-to-last-frame turned out to be all I needed.
- The referee: it's a GOAL when the ball's path crosses the line between the posts in the scoring direction, with a short cooldown so one shot counts once.


Under the hood
- Detector: stock COCO
yolo26s(ONNX) - Input: a recorded 1338×1074 clip at 60 fps (offline: live is the next step)
- Detection + decoding on Metis: ~250 fps
- Full pipeline (incl. drawing + encoding the annotated video): ~94 fps
On my laptop, the YOLO detection was ~94% of the processing time; on Metis that dropped to ~37%, and suddenly my own OpenCV drawing and video-encoding was the bottleneck (~63%). Now to be fair, this isn't a clean laptop-vs-Metis benchmark: my laptop run was totally unoptimized (plain model on CPU, no Apple MPS, no quantization), so I could perhaps have sped that side up too. It’s just satisfying to watch this bottleneck move, and the accelerator doing what it was meant to do, on a quick and dirty evening project.

I had to run inference remotely on one of my lab machines but the obvious next step is to turn it into a fun half-time live-camera game for World Cup 2026 watch parties with friends ⚽︎
This was a lot of fun, and not stressful at all. 🙂


