JustOnAir docs
View as Markdown

Hosted player

Put the player on any page with one iframe. It waits, starts by itself, handles reconnects, and ends cleanly.

Every stream has an embed_url, https://play.joacdn.com/{id}. It is a complete player page: embed it, or send the link.

HTML
<iframe src="https://play.joacdn.com/str_e1bzk3dxw9z9allei6n7"
  allow="autoplay; fullscreen; picture-in-picture" allowfullscreen
  style="aspect-ratio:16/9;width:100%;border:0"></iframe>

The allow list lets the player start by itself and go full screen. The style makes it fill the width of its container at 16:9; any fixed size works too.

What viewers see

WhenThe player shows
Before you go liveA waiting screen with the stream name and "Starting soon". It checks every few seconds; nobody has to refresh.
Going live"Going live", then the picture, 10–20 seconds after the publisher starts.
LiveThe video with play, volume, a LIVE badge, time since start, quality (Auto, 1080p, 720p, 480p), picture-in-picture and full screen.
Viewer paused or fell behindThe badge says GO LIVE. One click jumps back to the live edge.
Publisher drops for a momentThe last picture, blurred, with "Reconnecting…". Playback resumes by itself.
After you end the streamThe last seconds play out, then "Stream ended" with how long it was live.
Expired, cancelled or a wrong link"This stream isn't available" or "We couldn't find this stream".

Browsers only allow sound to start after a click. The player tries with sound first; if the browser refuses, it plays muted and shows Tap to unmute. Volume is remembered per browser. Keyboard: space or K play/pause, M mute, F full screen, L jump to live.

The stream name

The player shows the stream's name in the waiting room, over the video and on the end screen. If the name is only for you ("Member 4411 private session"), hide it:

Shell
curl -X PATCH https://api.justonair.com/v1/streams/str_e1bzk3dxw9z9allei6n7 \
  -H "Authorization: Bearer $JOA_API_KEY" -H "Content-Type: application/json" \
  -d '{"player": {"show_name": false}}'

Hidden means the name never reaches the public page at all. You can also set it when creating the stream, or with the switch in the dashboard's Stream settings.

Options on the address

Add these to embed_url:

OptionExampleEffect
title?title=Friday%20YogaShow this title instead of the stream name.
accent?accent=ff7a3dYour colour (6 hex digits) instead of JustOnAir lime, for the LIVE badge, buttons and progress.
muted?muted=1Start muted.
autoplay?autoplay=0Wait for a click instead of starting by itself.

Combine them with &: https://play.joacdn.com/str_…?title=Launch&accent=ff7a3d&muted=1.

Viewer counts

The player reports how many people are watching, so you see it live in the dashboard and in viewers on the stream:

JSON
"viewers": {
  "now": { "watching": 1240, "waiting": 85, "buffering_pct": 1.8, "measured_at": "2026-09-29T19:04:10Z", "exact": false },
  "peak": 1302,
  "peak_at": "2026-09-29T19:01:00.000Z",
  "watch_minutes": 18422,
  "source": "player",
  "cdn_counted_until": "2026-09-29T18:00:00.000Z"
}
  • Live, from the player. Up to about 400 viewers every player reports and the count is exact. Above that, only a random sample reports and the count is an estimate within about 5%, so a stream with 100,000 viewers sends the same small number of reports as one with 400. buffering_pct is the share of viewers whose video is stalled: if it climbs, lower your bitrate or check your upload.
  • Afterwards, from the CDN. About an hour later, the CDN's own logs give the exact count for every player, including your own players and apps. peak and watch_minutes switch to it (source: "cdn").
  • Nothing personal. Each page load reports a random id, whether it is waiting, playing, paused or buffering, and nothing else. No cookies, no IP addresses stored. Countries come from the CDN's logs, and only the total per country is kept.

GET /v1/streams/{id}/viewers returns the curve, minute by minute, and countries: the share of watch time from each country, from the CDN logs. GET /v1/streams carries viewers_now on every stream, so one call shows every live audience, and GET /v1/usage has watch_minutes per day.

Things to know

  • Anyone with the link can watch. The player is public by design. For members-only viewing, use your own player with short-lived links from your backend.
  • The player carries a small JustOnAir mark. Removing it is not an option yet.
  • Corporate networks. Some company firewalls block newly registered domains, and joacdn.com is new. If a viewer at an office sees an error while everyone else plays fine, that is the cause.
  • Delay. Viewers are 10–15 seconds behind the publisher.
  • Large audiences. The player and its status checks are served from the CDN, so a waiting room of 50,000 people costs the same to our servers as one of 50.