The live stats snapshot and its refresh window
Two independent queries feed the top of the page:liveStats returns a single snapshot object per live input — it is not a time
series. The values come from a rollup in ClickHouse that the relay mesh feeds;
the console just renders the most recent row for this input.
Because the console polls on a fixed interval, a value you read can be up to
one interval stale. A stream that just went live, or an encoder that just
stopped, will not be reflected in the stats until the next poll completes.
What each stat measures
Notes on the rendering, because the displayed value is not always the raw
field:
- Viewers is a point-in-time count of subscribers attached to this playback id right now, not a session total for the broadcast.
- Glass-to-glass is the median (p50) end-to-end latency across the last five minutes, not the current instantaneous latency of any one viewer. A single badly-connected viewer will not move the p50 much.
- Bitrate is reported by the API in kbps and divided by 1000 for display,
so
4200renders as4.2 Mbps. It is the delivered, per-viewer rate — what subscribers are actually receiving — not the rate your encoder claims to be pushing at ingest. - Dropped is a percentage over the same five-minute window as
glass-to-glass, printed to two decimal places, so small non-zero loss stays
visible instead of rounding to
0.
Why a stat reads as a dash
A— means “nothing to show”, and there are two different reasons for it:
- The snapshot has not loaded. If the
liveStatsquery has not resolved (or errored), all four tiles show—, including Viewers. - The value is zero-guarded. Glass-to-glass and Bitrate render
—rather than0when the underlying field is0, because a zero there means “no measurement yet” rather than “zero milliseconds” or “zero Mbps”. This is normal in the first moments after an encoder connects and before any subscriber has pulled media.
0 and 0.00 honestly. Viewers 0 on a live stream is a real
statement — nobody is watching — not a missing measurement.
Reading the numbers when a stream looks wrong
The four values split cleanly into an ingest side and a delivery side, which is what makes them useful together:- Viewers
0, but the badge says LIVE. Ingest is fine; the relay is accepting your publish. The problem is on the playback side — wrong playback id in the player, or a signed-playback policy rejecting subscribers. Check the playback id and signed URL in the Setup tab before touching the encoder. - Dropped climbing while Bitrate falls. Delivered bitrate is what viewers receive, so these two moving together points at the path between the relay and subscribers, or at a publisher uplink that can no longer sustain the encode. Compare against what your encoder reports it is sending.
- Dropped climbing while Bitrate holds. Media is still flowing at rate but packets are being lost. Treat it as a network-path problem rather than a capacity one.
- Glass-to-glass rising with Viewers and Bitrate steady. Latency is
accumulating somewhere in delivery. The edge serving this input is printed in
the page subtitle as
edge <relay_region>— note it before you escalate, since a regional edge is the usual explanation for a latency shift that no other signal reflects. - All four dashed while the badge says LIVE. The
liveStatsquery is the thing that is failing, not the stream. The live-input record and the stats snapshot are separate queries; one can fail while the other succeeds.
Live and offline states
The page treats an input as live when any of these hold:is_live is true, or
status is active, or status is recording. That drives three things at
once — the LIVE/OFFLINE badge, whether the hosted preview iframe is mounted,
and whether the LIVE EDGE indicator appears under the player.
When the input is offline the preview is replaced by a placeholder that prints
two facts worth reading:
first seen <timestamp>fromfirst_seen_at, ornot yet ingestedif the input has never received media. “Not yet ingested” on an input you believe is configured means the encoder has never successfully reached the relay — check the key, not the player.recording on/recording offfromrecording_enabled, so you can tell before the fact whether this session will produce a VOD asset.
/api/streams/embed/<playback-id>), so if the preview plays, the public embed
plays.
Embed URL parameters
The Embed tab builds an<iframe> snippet live from four checkboxes. Each
checkbox appends one query parameter to the embed URL; unchecked options are
omitted entirely rather than sent as =0. The base URL is:
The default state in the console is Low-latency and Autoplay on, Signed URL
only and Show viewer count off, producing:
?. Copying the snippet with the copy button gives you exactly what
the preview pane shows.
Signed playback URLs
The unsigned MoQ subscribe URL,moq://relay.clutchcall.dev/playback/<external_input_id>,
is not authenticated — any client that knows or guesses the input id can
subscribe. Generate signed playback URL in the Setup tab calls
streams.liveInputs.mintPlaybackToken with a TTL of 3600 seconds and mints an
Ed25519 JWT against your org’s active playback signing key.
The mutation returns the input id, the token, and expires_at. The console
composes them into:
mod_streams
verifies the tok= claim against the public half of the signing key cached in
Redis before it allows the SUBSCRIBE. Key lifecycle and rotation are covered in
Authentication.
Recordings from this live input
The Recordings tab lists VOD assets produced by this live input. The console fetches the org’s assets withstreams.assets.list and filters client-side on
source_live_input_id matching the current input id; the resulting count is the
number badged on the tab. Whether a session produces an asset at all depends on
the input’s recording_enabled flag, which the offline placeholder prints.
Two consequences of the list being polled at its own 60 s interval and filtered
client-side:
- A recording that has just been produced can lag the live stats by up to a minute before it appears in the tab.
- The tab reflects the first page of assets the list procedure returns, so a very large asset library can outrun what is shown here.
Resetting the stream key
Reset stream key callsstreams.liveInputs.resetKey and is immediate and
disruptive: any encoder still using the previous key starts failing as soon as
the mutation lands. The new key is returned in cleartext exactly once, in a
dialog, and is never retrievable afterwards — the detail page and the list only
ever render stream_key_preview. Copy it into your encoder config before
dismissing the dialog.
Related
- Telemetry — metrics, traces and the rollup stores
- Telephony Metrics — definitions and healthy ranges
- Authentication — signing keys and token rotation

