OnAir turns "click a game" into a live HLS stream that stays up. It collects candidate streams from pluggable source adapters, probes and ranks them, plays the best one, and when that stream stalls, errors, expires or freezes, it fails over to the next candidate without the picture ever going black. The repository ships no sources; the demo runs against two local fixture streams that can be broken on command.
Never black
Two video elements, one visible and one staging. A replacement stream loads out of sight and becomes visible on its first decoded frame. The current picture is torn down only once something better is on screen. A browser test tier runs a real decoder through the swap to prove it: the visible element never drops below the have-current-data ready state, and position only ever moves forward.
Three detectors, because each failure hides from the other two
- A stall state machine catches a starved buffer. Two states, watching and stalled; progress resets the timer.
- A fatal-error classifier tells an expired token, which means re-fetching the URL and staying, apart from a dead source, which means moving on. The same status code means different things before and after the first frame.
- An off-air check catches a stream that returns success on everything while its live edge has stopped moving. The player library sees nothing wrong with that.
An escalation ladder, not a retry loop
Continuity
Sources run 45 to 100 seconds apart. When a stream carries wall-clock timestamps, the replacement seeks to the same instant in the broadcast instead of the live edge, so a failover does not skip or repeat play.
Click to play

Status
Works end to end against the fixture source; the embedded-player rung is covered by unit tests only. macOS only, not packaged or signed for distribution. 527 tests across 32 suites plus seven real-decoder browser tests. Adapters for anything beyond the fixture are the operator's to write, and the repository's own guidance is to add adapters only for streams you are permitted to access.