Workload · Reading your audience numbers

Live stream analytics: who really watched, and what to fix before the next show

Live stream analytics answer two questions: how many people really watched, and whether the picture held up for them. A single viewer figure answers neither, because peak, reach, time watched and buffering each measure something different and lead to different fixes. Here is what each number counts, what a Primcast channel shows you, how to measure the rest in your own player, and what to change when a number looks wrong.

The short version
  1. Peak tells you about capacity; watch time tells you about the show
  2. A viewer count from server requests is worked out, not observed, so treat it as an estimate
  3. If the encoder's rate holds and viewers still stall, look past your uplink
  4. Report restream platforms separately: adding them up can count one person twice

Seven numbers, and what each one really counts

Each number below answers one question and misleads you on another. These are general meanings rather than a standard: every tool draws its own lines, so read its definition before you compare two reports.

NumberWhat it generally countsWhere it misleadsWhat it helps you decide
Peak concurrent viewersThe most players open at the same momentSays nothing about how long anyone stayedWhether your viewer limit was big enough
Distinct viewersDifferent people or devices across the whole show, matched on whatever the tool can see, such as a login or deviceA phone then a TV can count as two; a family on one TV counts as oneHow far the show reached
Sessions or playsEach separate time a player startedA viewer who drops and comes back adds anotherRead against distinct viewers: far more sessions than people suggests people kept getting knocked off
Watch timeTime spent actually playing, added up across everyoneA player left running in an empty room still adds upWhether the show held people
Start-up timeThe wait between pressing play and the first pictureAn average can hide a slow minorityWhether people give up before they see anything
BufferingHow often the picture stopped to wait for data, and for how longA count alone treats a blink and a long freeze as equalWhether the encoder or delivery needs work
LocationA country or city worked out from the viewer's networkIt is approximate, and a VPN shows the VPN's locationWhere your audience is and whether your access rules fit

If you want careful definitions to borrow, player documentation is a good place to look. Android's Media3 library separates time actively playing from time a viewer spent waiting, and gives rebuffer time as a share of playing plus waiting. Its guide also points out that a buffering state can be the first load, a real rebuffer or a wait after a seek, which is why those should not be lumped together. Apple's AVFoundation access log keeps comparable fields: stalls, duration played, and time until the item is ready to play.

Why two honest reports can disagree

Because nobody counts people directly. With HLS, which our channels play out alongside DASH, a player downloads a playlist and then short media segments, and on a live stream it keeps reloading the playlist to find new ones (RFC 8216 describes this). A server sees requests. Any viewer figure taken from them has to be worked out, and that step is where tools part ways: how long a gap ends a session, what makes two requests the same person, whether a muted background tab counts.

So our advice is to pick one tool and one definition, keep them, and compare your shows with each other. A trend measured the same way each week tells you more than a single figure held up against someone else's dashboard.

What your Primcast channel shows you

On live video hosting, the Live tab of each channel is where you read a show as it happens:

  • Status gives the encoder's address, the rate it is sending, how long it has been on air, how much is going out and how many are watching.
  • Viewers lists each viewer with country and player while the stream runs, and the list downloads as a spreadsheet.
  • Transfer for the month can be watched in the dashboard as it grows, as the video CDN page explains.
  • Paid shows add a second, firmer count: the paywall in our player gives you a daily sales chart, how many members joined or left, and spreadsheets of every sale and viewer.

Our CDN page describes that list as who is watching this minute, so treat a download as a snapshot. Take one near your peak and another as you wrap, unless you have checked that a single file covers the whole show.

Two different places get called a location. The country in the viewer list describes the viewer. The nearest of our 5 cities is where the video is served from, and a viewer in one country can easily be served from a city in another.

A quick read while you are on air

A short routine during the show gives you time to act. Hand it to whoever is not running the cameras.

  1. Compare the rate the encoder is sending with the bitrate you set. If it sags, start with your own line and encoder, and expect every viewer to share the problem.
  2. Watch the viewer count against your channel's limit. Our CDN page calls that figure a hard limit, so a crowd close to it needs a decision before the next show, not during it.
  3. Scan the country and player columns when complaints come in. Complaints that cluster in one player or one country point somewhere much narrower than "the stream".
  4. Note the clock time of anything odd, such as a sudden drop in viewers. You will want to line it up with your rundown afterwards.

Measuring watch time and buffering in your own player

Buffering happens on the viewer's screen, so the player is the place to measure it. Our player page notes that a stream's HLS and DASH addresses are standard ones, so Video.js, Shaka or an app's own player can play them if you build your own. Once you do, a few standard browser events give you start-up time, stalls and time played.

The sketch below is ours, not a Primcast feature. It suits a player you built yourself: it needs a video element on your own HTTPS page, plus an address on your site that stores what it receives. Run it before playback starts: if it misses the first play, start-up and stalls stay empty. The report arrives as plain text holding JSON, so have /stats parse the body itself. Try it on a rehearsal first.

// Your own page, your own video element. /stats is your own address.
const v = document.querySelector('video');
const report = { id: crypto.randomUUID(), startMs: null, stalls: 0, stallMs: 0 };
let askedAt = null, stalledAt = null;

v.addEventListener('play', () => { askedAt ??= performance.now(); });
v.addEventListener('playing', () => {
  const now = performance.now();
  if (report.startMs === null && askedAt !== null) report.startMs = Math.round(now - askedAt);
  if (stalledAt !== null) { report.stallMs += Math.round(now - stalledAt); stalledAt = null; }
});
v.addEventListener('waiting', () => {
  if (report.startMs !== null && !v.seeking && stalledAt === null) {
    report.stalls += 1;
    stalledAt = performance.now();
  }
});

function playedSeconds() {
  let s = 0;
  for (let i = 0; i < v.played.length; i++) s += v.played.end(i) - v.played.start(i);
  return Math.round(s);
}
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    const openMs = stalledAt === null ? 0 : Math.round(performance.now() - stalledAt);
    navigator.sendBeacon('/stats', JSON.stringify({ ...report, stallMs: report.stallMs + openMs, playedS: playedSeconds() }));
  }
});
  • Keep the latest report per id. The block sends each time the tab is hidden, and every report carries running totals, so adding them up would double count. Anything played after the last hide is not reported.
  • The id marks a session, not a person. It is made fresh on each page load and never stored. Counting distinct viewers needs something steadier, such as a sign-in.
  • Start-up is timed from the play event, so it means something when a viewer presses play or your code calls play(). With the autoplay attribute, that event can arrive once the video is already ready, and the figure reads close to zero.
  • The first load and seeks are left out of the stall count, for the reason Media3 gives above. A pause during a stall adds the whole pause to that stall's length.
  • Time played comes from the played ranges, so a stretch watched twice after rewinding counts once. On a straight live viewing the two match.
  • Stall share is your headline figure: add up stallMs across sessions, then divide it by total played time plus total stallMs. playedS is in seconds, so multiply it by 1,000 first. It is a close cousin of Media3's rebuffer ratio.
  • In a phone app, use the platform's own tools instead: PlaybackStatsListener in Media3, or the access log in AVFoundation.

What to change when a number looks wrong

Find your symptom, then change one thing and compare at the next show. The causes here are our reading of what usually lies behind each pattern, so treat them as the first thing to check, not a verdict.

What you seeCheck firstWhat to change
Encoder rate sags and everyone complainsYour upload, measured on the broadcasting machineKeep video plus audio to about two thirds of your upload, or drop to 720p. On a shaky line use SRT, available from Starter up
Encoder rate holds, viewers buffer anywayThe keyframe intervalSet a fixed 2 seconds and turn off scene-change keyframes, as our live streaming tutorials explain
Stalls mostly on weak or mobile connectionsWhether one bitrate is being sent to everyoneLower the bitrate, or use adaptive bitrate transcoding on Platinum so the player can step down before the picture freezes
Complaints from one regionReach from there: the data centers page lists a test IP and speed test for each cityAsk a viewer there to run it and send you the result before you change the encoder
Complaints from one playerPlay the HLS link yourself on that device, on mobile data if you canIf it fails there alone, the fix belongs to that player or device
Countries you did not expectWhether your link has been shared aroundUse the country, IP and website rules, or expiring signed links, both on every plan
Peak close to your viewer limitWhether it was a one-off nightMove up a plan for regular crowds, or use the event builder for a single big date
Viewers leave at the same momentYour rundown at that clock timeIf nothing stalled, the cause is the show rather than the stream: a long break, a dull segment, a late start

Writing it up for a sponsor or your board

A good report says what was counted as plainly as how many. Our event page suggests keeping the viewer spreadsheet for exactly this.

  • Name the definition next to the figure. "Peak of viewers at the same time, read from the Live tab" survives a follow-up question; "views" does not.
  • Report restream platforms on their own lines. People watching on YouTube, Facebook or Twitch are watching on those platforms, so use each platform's own figures and do not total them with your player's: someone can be on two at once.
  • Say when a snapshot was taken, so nobody reads a peak-time list as the whole audience.
  • Trim before you forward. Open the spreadsheet and remove what the reader does not need, and share totals by country rather than rows where you can. Under EU rules, an online identifier can be personal data. That is general information, not legal advice.

Questions people ask

How do I find out how many people watched my stream?
Decide which figure you mean first: the biggest crowd at one moment, or the reach across the whole show. On a Primcast channel the Live tab shows how many are watching and lists each viewer with country and player. If you sell tickets, the paywall's sales spreadsheet is your firmest headcount, though a family sharing one ticket still counts once.
How much buffering is too much?
We know of no official threshold that fits every audience, so we will not quote one. Measure the share of time spent stalled, keep the definition fixed, and compare each show with the last. A rise after you changed the encoder settings or the venue tells you more than any industry figure could.
Why don't my numbers match the ones on the social platforms?
They are counting different audiences with different rules. A restream goes out to YouTube, Facebook or Twitch, and each platform counts its own viewers by its own definition. As we read it, your channel's list covers people on your own player, not those watching on the platforms. Read them side by side and do not expect them to agree.
Can I see which city my viewers are in?
The viewer list gives each viewer's country. Anything finer is a best guess worked out from a network address, so treat city figures from any tool as approximate. Do not read the CDN's serving city as the viewer's home: it is simply the nearest of the 5 cities the video is delivered from.

Run your next show on a channel you can read

Every channel comes with a Live tab, a viewer list you can download and a CDN that plays from the city nearest each viewer.

Start your live channel

Read next