Token renewal
How a viewer or a publisher keeps a session going past its token's expiry, and what each side must do.
A token is short on purpose, and the relay enforces it: a session ends when its token runs out. Watching and publishing go on only because the client presents a fresh token on a new session before then. This page is what that costs your code, for each kind of client.
The rule at the relay, for every session:
| Token | The relay closes the session at |
|---|---|
| viewer (reads) | exp, plus the clock skew, plus a watch grace |
| publisher or controller (publishes) | exp, plus the clock skew |
In the managed service the skew is 2 s. The watch grace is the time a viewer's session may outlive its token, so that a late renewal does not cut the picture; the control API sets it (600 s unless the operator chooses another). Nothing in a token can be extended: there is no message that re-authorizes a live session, so a renewal is always a new session.
Viewers
With the player and your token-url route you write nothing for renewal. The
player does it:
- It holds a token of about 120 s (
ttl, 1 to 3600). - About 15 s before the token expires, it asks for a new one: your
token-urlroute with the seat it holds ({ "seat": "se_...", "join": false }), or, for a public stream,POST /v1/play/{id}/tokenwith the seat. For a token shorter than 30 s it asks at half the token's life, and never sooner than 5 s after the token arrived. - It opens a second session with the new token, waits for the next keyframe on both, switches at that group boundary, and closes the old session. The decoder is not reset. This is make before break: one group arrives twice.
- The old token is never used again, and each renewal gets a new token id.
The time comes from the token itself (its issue and expiry times), counted from when the token arrived. A viewer whose own clock is wrong renews on time.
Your route is called once per renewal, per viewer: about once for every
ttl minus 15 s. It must answer 201 with the descriptor each time. If it
answers an error, the player tries again after 2 s, then 4 s, doubling to
30 s, until the relay closes the old session at its deadline; then the
player reconnects and keeps asking.
Limits per seat
- At most 6 tokens a minute for one seat (
429 rate_limited). A renewal every 105 s uses a small part of that; the limit is for loops, such as a client that reconnects as fast as it can. - A seat holds its two newest tokens. Minting a third closes the oldest's session. During a renewal a seat has two sessions, which is why a seat can never use more than two.
- A seat that has lost its heartbeat is gone (20 s without one, 60 s for a
hidden tab, Viewer tokens). For a
public stream
POST /v1/play/{id}/tokenthen answers410 seat_lostand the player shows "Your seat was given up. Reload to watch again."
Hidden tabs
A browser slows a hidden tab's timers, so a tab that is hidden does not make the handover. The player handles it in three ways:
- Back in view past its renewal time, the tab moves to a fresh session with a fresh token at once.
- If the tab was hidden past the token's deadline, the relay has already closed the session or refuses its next request (code 5, an expired token). The player gives that session up and reconnects with fresh tokens.
- The seat survives: a hidden tab says so in its heartbeat and keeps its seat for 60 s. A tab hidden longer than that loses the seat and shows the message above on return.
Sound that plays on while the page is hidden is a different setting
(background-audio, Embed the player); it does not
extend the token.
Turning it off
In the JavaScript API, renew: 'off' in the player options never hands
over (for tests). The session then ends at its deadline and the player
reconnects the ordinary way, with a visible gap.
Revoking a viewer
Renewal is also how a viewer is removed. A seat your backend stops minting
tokens for (your session ended, the seat was kicked, the stream was deleted)
loses the relay within one token lifetime plus the grace. A kick
(DELETE /v1/streams/{id}/viewers/{seat}) and deleting the stream close the
sessions at once. So a short ttl makes "stop minting" a faster way to
remove someone; the cost is only more calls to your route.
Publishers
A publishing session ends at its token's exp plus the skew, with no grace.
The device must connect again with a fresh token.
nearglass publish --api ... --secret-key-file ... --stream ... --token-ttl Nasks the API for a new token at each connect. With--token-ttl 10on a test stack the relay closed the session about 12.7 s after it began, with the reason "token expired", and the publisher was back on the relay with a new token within a few milliseconds. The relay's record for the session saidexpired.- A token given once (
--descriptor,--token-file, the C library'snearglass_conn.token) is used again at every reconnect, so the device goes on only until that token expires. Mint it for as long as you need (ttlup to 7 days) and replace it before then. See Publisher tokens. - Controller tokens (a driver's turn) end the same way, at
expplus the skew, so a turn ends at the relay even if your backend never closes it.
A publisher that is refused (an expired or closed token) reconnects at once,
in a tight loop, with no pause growing between tries. Do not let a device
retry in a loop on a refusal: when a connect is refused, ask your backend for
a new token and wait a few seconds. Run on a test stack, nearglass publish
with an expired token reconnected hundreds of times a second.
Native viewers
A native viewer (the C library) takes one token when you start it. It does
not renew: its session is closed at the token's exp plus the skew plus the
grace. Before then, start a new session with a fresh token from your backend,
and close the old one once the new one is playing if you cannot afford a gap.
A longer ttl (up to 3600 s) gives a longer session, and a seat you stop
minting for still leaves within that time.
What was run
- A publisher renewing through
--apiwith a 10 s token, on a test stack with the relay's rules as shipped (above). - The API's side of renewal for viewers: a held seat gets a new token on
every call, up to 6 in a minute, then
429 rate_limited; an unknown seat atPOST /v1/play/{id}/tokenis410 seat_lost; seats lapse at 20 s (visible) and between 50 s and 62 s (hidden).