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.
<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
| When | The player shows |
|---|---|
| Before you go live | A 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. |
| Live | The 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 behind | The badge says GO LIVE. One click jumps back to the live edge. |
| Publisher drops for a moment | The last picture, blurred, with "Reconnecting…". Playback resumes by itself. |
| After you end the stream | The 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:
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:
| Option | Example | Effect |
|---|---|---|
title | ?title=Friday%20Yoga | Show this title instead of the stream name. |
accent | ?accent=ff7a3d | Your colour (6 hex digits) instead of JustOnAir lime, for the LIVE badge, buttons and progress. |
muted | ?muted=1 | Start muted. |
autoplay | ?autoplay=0 | Wait 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:
"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_pctis 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.
peakandwatch_minutesswitch 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.comis 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.