Cases

Canadian hockey-streaming startup

An automatic hockey camera that runs on one desktop per rink

For a Canadian startup that streams amateur hockey, we built player tracking and a virtual camera that frame a live game from fixed cameras, with no one filming and no moving parts. The rebuilt tracker is nearly 3× faster, and the full chain fits a 30 ms frame budget on ordinary hardware.

Key results
  • A software camera follows the play, with no operator and no motorised camera
  • A whole live game runs on one ordinary desktop per rink
  • The client’s team sets up each new rink once, in a point-and-click tool
Indoor hockey rink seen from a high camera, with detection boxes on every player and both goalies, labelled by team, and a frame around the area of play
Client
Canadian sports-streaming startup
Industry
SportsTech, hockey streaming
Team
2 engineers
Duration
About nine months
Model
Four stages, report and build each
Platforms
Linux, Windows; CPU or NVIDIA GPU

In short

Amateur hockey is worth streaming only if it is worth watching. A fixed wide shot of the rink is cheap but dull: players are small, and the play sits in one corner. Amateur games have no camera operator, so the framing had to come from software.

For a Canadian startup that streamed amateur and youth hockey from cameras fixed in rinks, two It-Jim engineers built the computer vision that does the operator’s job. It finds every player on the ice, works out where the play is, and moves a virtual camera there smoothly, live. Everything had to finish within about 30 ms per frame on ordinary hardware. After profiling the whole chain, we rebuilt the tracker to run nearly 3× faster, and a whole live game now runs on one desktop per rink.

What it gives the business

  • ~3×faster tracker after the rebuild, and 4× faster on its slowest frames
  • 24 msfor the full chain per frame, inside the 30 ms budget of a live stream
  • ~1.2CPU cores for a whole live game on a mid-range desktop
  • 1setup per rink, done by the client’s team, then every game runs by itself

Need computer vision that keeps up with a live stream?

Send us a few game recordings. In two weeks we tell you what can be detected and tracked reliably on your footage and your hardware, and what full development would take.

Book a two-week technical research

About the client

Amateur hockey on camera

The client was a Canadian startup that streamed amateur and youth sports, hockey first, from cameras installed in rinks. Parents, players and coaches watched games live or on demand.

The business could only grow if each rink ran on its own: a camera on the wall, a stream to the viewers, and nobody in the stands filming.

Canada
Client’s market
Hockey first
Amateur and youth games
Live and on demand
Streams from cameras fixed in rinks

Main challenges the customer faced

Three problems to solve at once

Business

TV-style framing with no one behind the camera

A camera that shows the whole rink is cheap, and dull to watch: players are small and half the ice is empty. Amateur games have no camera operator.

The client needed a view that follows the play, made by software from the fixed cameras, for every game at every rink.

Technical

Fast skaters, a busy background and 30 ms per frame

  • Players move fast, change direction, crowd together near the net and overlap on screen.
  • The frame holds more than the ice: boards, benches, stands and spectators who also move. Anything moving there could pull the camera off the play.
  • One camera can’t see the whole rink, so two wide-angle views had to be joined into one panorama of up to 180° with no visible seam.
  • It all had to fit a live stream: decoding, tracking and framing within about 30 ms per frame.
Delivery

One system, two kinds of hardware

The client ran the system on more than one kind of machine. The code had to work CPU-only and with an NVIDIA GPU, and read and write live video streams as well as files.

What we did

Two engineers, four stages

Each stage closed with a written report and a working build, and each started from what the previous report showed.

  1. First prototype. Player detection, masking of the rink and a first region-of-play tracker, tested on the client’s own game footage.
  2. Setup tools the client runs on its own. The prototype showed where false detections came from, so we built a GUI to draw the rink mask and set up stitching. From then on, the client’s team could open a new rink without us.
  3. Speed. We profiled the whole chain on a live stream, then built a new tracker and camera controller around what the profiling showed.
  4. Panorama v2. A stitcher for two cameras with fewer manual steps and a choice of projections.

Solution

Every player on the ice, on a CPU

Why it matters: the camera can only follow the play if it knows where every player is, in real time, on ordinary hardware. If it reacts to people on the bench or in the stands, viewers watch the crowd instead of the game.

Before looking for players, the system masks out everything that isn’t the playing surface. The mask is drawn by hand in the setup tool or found automatically from the colour of the ice, once per rink.

Rink lighting stays the same through a game, so the empty ice works as a stable background. The detector compares each frame with it and keeps what changed. Players are darker than the ice, so a one-sided comparison is both faster and cleaner. Shapes are then filtered by size and fill, scaled by their place on the ice, because a far player looks smaller than a near one.

Foreground mask, filtered player shapes and tracked players with their trails on an amateur hockey rink
From the project: the foreground mask, filtered player shapes, and tracked players with their trails.
Map of size coefficients across the rink with detected player shapes in boxes
Size map: far players (top) are expected to look smaller than near ones (bottom).

Solution

Tracking and framing the play the way an operator would

Why it matters: false detections make the camera twitch, and lost players make it miss the play. This is the step that frames the game for the viewer.

Each player becomes a track. A new track counts only after it is confirmed on 30 frames in a row, and a track is dropped after 10 frames with no match, so a passing shadow never moves the camera. An alpha-beta filter smooths each track and predicts where the player goes next. When players pass close to each other, tracks are matched by how much their boxes overlap, strongest match first.

The system then groups players into clusters and weighs each one. A small cluster far from the action is dropped when that makes the frame much tighter, so one player skating to the bench doesn’t widen the shot. The frame keeps its aspect ratio, stays within the zoom limits and never leaves the rink.

A camera controller smooths the frame over time and predicts its next position, so the view pans like an operator’s and holds steady through a quick pass.

1 · Watch only the ice STANDS · BENCH ICE

Only players on the ice can move the camera.

2 · Confirm before following FRAMES → PLAYER 30 FRAMES IN A ROW CONFIRMED · CAMERA FOLLOWS SHADOW DROPPED · CAMERA IGNORES IT

A passing shadow is dropped before it can jerk the camera.

3 · Frame the play VIRTUAL CAMERA TO THE BENCH · LEFT OUT

One player heading to the bench does not widen the shot.

Simplified schematic, not measured data.

Solution

Two cameras, one rink, no visible seam

Why it matters: two cameras joined badly show a seam exactly where the play crosses.

The stitcher joins two wide-angle cameras into one panorama of up to 180°. Version 1 needed a calibration and several manual steps per camera. Version 2 needs only 4 to 10 matching point pairs, set in a GUI, and computes the rotation between the cameras automatically. Spherical, cylindrical and flat projections can be compared on the spot. The setup is done once per rink.

Two rink cameras stitched into one wide panorama with boxes around each player
From the project: two cameras stitched into one rink panorama, with tracked players.

Solution

Built around where the time actually went

Why it matters: a tracker that keeps up on a test file can still fall behind on a real game, and viewers notice a stall at once.

We profiled the whole application on a live game stream: CPU-only and with CUDA, with software decoding and with the NVIDIA hardware decoder. One finding shaped the rest: on large frames, copying images between the CPU and the GPU took more GPU time than the image processing itself.

We rebuilt the tracker and the camera controller around what we found, moved colour conversion to a faster library, and made every stage configurable with a debug view. The application reads one live stream and sends out two: the panorama and the tracked camera view.

Every stage can be tuned and switched to a debug view.

Key results

What changed, measured

A live stream leaves about 30 ms per frame for everything. We measured the tracker, the full chain and the load on a desktop.

  1. 1
    Same recorded game, same laptop CPU

    No stalls on busy plays: the tracker is nearly 3× faster

    The new tracker runs nearly 3× faster on average and 4× faster on its slowest frames. Busy moments near the net no longer eat the frame budget, and the rest of it is left for decoding and streaming.

    On the same laptop and recording, the full chain took about 24 ms per frame on average: video decoding about 16.8 ms, colour conversion about 2.5 ms, tracking 4.6 ms. That is inside the 30 ms budget of a live stream, with room to spare. Measured CPU-only on an older laptop with an Intel Core i7-3630QM, on a recorded game.

    Tracker time per frame
    Full chain per frame, against the 30 ms live budget
    Old tracker: about 32 ms, over budget
    New tracker: about 24 ms, 6 ms to spare
    Inside the 30 ms budget No stalls near the net
  2. 2
    Live game stream, mid-range desktop

    A live game on one desktop

    On a desktop with a GeForce GTX 1060, on a live game stream, the whole application used about 1.2 CPU cores and about 1 GB of RAM with tracking on, measured with the system monitor and nvidia-smi. Our own code used about 200 MB of GPU memory; the rest belonged to NVIDIA’s hardware decoder and encoder.

    For the business, that means no special rig per rink: one mid-range desktop carries a whole game.

    A whole live game on one desktop GeForce GTX 1060, tracking on
  3. 3
    Every new rink

    Set up once per rink, by the client’s own team

    The rink mask and the panorama are configured in a GUI once per installation, by the client’s team. After that, every game is framed by itself. The client doesn’t need us to open a rink, so it can add rinks as fast as it installs cameras.

    Panorama setupv1calibration and several manual steps per camerav24 to 10 matching point pairs in a GUI
    Rink mask1setup per rink, drawn in the GUI or found from the colour of the ice
    Every game after setup runs by itself Set up by the client’s own team

Business results

What it changed for a rink-streaming business

A business like this grows by the number of rinks it covers. With the framing automatic and the setup in the client’s hands, a new rink takes a camera, a desktop and one setup.

  • Growth by rinks, not by staff. Every new rink gets a camera and a one-time setup, and its games are framed with no one filming.
  • Games worth rewatching. A view that follows the play reads like TV coverage, which a fixed wide shot of the whole rink never does.
  • No special hardware. The tracker keeps up on an older laptop CPU, and a live game runs on one mid-range desktop.
  • No waiting on outside engineers. The client’s own team sets up every new rink in the GUI.
~3×Faster tracker on average, 4× on the slowest frames
24 msFull chain per frame, against a 30 ms live budget
0Moving parts: the camera move happens in software, on fixed cameras
~1.2CPU cores for a whole live game
180°Rink panorama from two cameras
1Setup per rink, by the client’s own team

Features delivered

What we shipped

  • Player detection: rink masking, manual or automatic
  • Multi-player tracker: track confirmation, dropping and prediction
  • Region-of-play estimator: player clustering and outlier rejection
  • Camera controller: smoothing, prediction and zoom limits
  • Panorama stitcher v2: two cameras, three projection types
  • Setup GUI: rink mask, stitching points and panorama tuning
  • Live-stream processing: CPU and CUDA modes, NVIDIA hardware decoding, two output streams
  • Reports and documentation: profiling and research reports at each stage

The technology we used

Stack

Languages and libraries
C++OpenCV (CPU and CUDA)FFmpeg
Computer vision
Background subtractionAlpha-beta filteringHierarchical clustering
Stitching
HomographyCamera-rotation estimationSpherical, cylindrical and planar projections
Video and platforms
NVIDIA hardware decode and encodeRTSP streamingLinuxWindows

Let’s Talk About Building AI That Works in the Real World

No vague promises. No pressure. Just a real conversation with our technical leadership to understand your needs and explore the best next steps.

Tell us about your project
Chat on WhatsApp
File upload (optional, up to 15 MB)

By submitting this form, you agree with our Privacy Policy

What Happens Next?
  1. Your message goes straight to our core team – not a sales department.
  2. You’ll talk directly with our CEO, CTO, or a domain expert for a consultation-style first call.
  3. We’ll ask the right technical questions to understand your challenge and scope.
  4. If we’re a fit, we’ll follow up with a proposed path forward.

More Projects Like This

Fanaty

Fanaty

A C++ stitcher that joins two sideline cameras into one full-pitch 4K panorama at 30 FPS on a CPU, after a consultation that made Fanaty’s processing eight times faster.

Tennis rally detection

Tennis rally detection

Computer vision that finds the rallies in amateur tennis matches and cuts the video by about 70%, on a cloud server with no GPU.

Postround

Postround

It-Jim built a cross-platform mobile app for Postround that detects and reads golf scorecards to keep player statistics

Pardigm

Pardigm

Hormone tracking application powered by Computer Vision with 93%+ accuracy in real-life conditions.