Transcript-verified video-only gate
An audio-only room tells every participant the same story at join time: you may talk, and everyone can hear you, but your camera and screen-share stay off until the moderator has proof you are a genuine speaker. The gate that enforces this is the transcript-verified video-only gate — a server-side grant transform that sits between the audio-only room policy and the LiveKit token mint. This page is the integrator’s map of it: why the ceiling exists, what the widen predicate actually checks, where in the request path it runs, and the two hard negatives it is designed never to allow. The channel-level overview is Video: rooms, embeds, recording, and broadcast; this page is the grant-semantics contract behind theaudio_only flag those surfaces configure.
1. Participant-grant semantics: a ceiling, never a ladder
Orbit’s video rooms mint an effective grant per participant — the join response’spermissions.can_publish plus a per-source publication allow-list
(canPublishSources) baked into the LiveKit JWT. In a full-video room, a
publishing tier (panelist, host) gets camera, screen-share, and
microphone sources. A subscribe-only tier (viewer,
hidden_supervisor, a lobby hold) gets no publish capability at all.
The audio-only policy applies a ceiling on top of that: every publisher’s
allow-list is clamped down to the audio sources (microphone) at the token
mint. The ceiling is authoritative server-side — even a client that ignores
the audio_only room-metadata hint cannot publish camera or screen-share
video, because the minted JWT itself carries the clamped source list.
Two consequences follow from the ceiling model:
- Audio-only is not widenable in principle. The policy bans camera and screen-share publishing from the whole room; your client cannot talk its way back into video by sending anything extra on join. The only way video returns is the gate’s own widen path, below.
- The ceiling can never create a publisher. A
viewerorhidden_supervisorgrant hascan_publish: false. Neither the audio-only clamp nor the gate ever flips that totrue— they only editcanPublishSourcesfor a participant who was already a publisher. A widening operation on a non-publishing tier is a no-op by construction, the same rule the route-layer per-source override runs: an allow-list narrows a non-publisher, it never widens one.
2. The helper contract: clamp, verify predicate, widen
The gate is a pure transform on the grant — no I/O, the same shape in mirror as in mint, so the decision is deterministic and auditable. Read as three separate clauses, they describe the whole lifecycle:- Clamp (before verification) — the grant comes back with the
publication allow-list intersected to the un-widened audio tier. Camera,
screen-share, and screen-share-audio are all dropped; whoever held only
microphonekeeps it. If the participant was never a publisher, the grant comes back unchanged — the clamp is a ceiling, not a ladder. - Verify predicate — a pure, fail-closed decision on the signed-speaker audio cluster’s end-to-end latency against the caller’s tolerance window. When no tolerance is declared the widener is always admitted; when the latency cannot be read or the value is malformed it is always denied. The gate widens only when this predicate comes back true.
- Widen (after verification) — exactly
cameraandscreen_shareare unioned onto whatever sources the publisher already holds. The audio-leg source is never added, non-video sources already present are preserved, and no subscriber is ever promoted into a publisher. The two video sources are the only thing the gate can ever widen; nothing else moves.
microphone, the gate’s own source vocabulary excludes it —
there is nothing to add there — and excludes the screen-share audio leg for
the same reason the audio-only ceiling does: letting it in would re-open a
policy the room explicitly banned.
3. Where the clamp applies upstream: the route layer, not a toggle
The route layer applies the gate before the access token is minted — at grant materialization, not at media runtime. The flow onPOST /video/rooms-scheduled/:id/join looks like this:
- The base tier’s grant is resolved from the requested
participant_tier(after host downgrade or lobby hold). - The audio-only room policy clamps the publisher’s source list down to the audio ceiling.
- The transcript-verified gate re-clamps to the un-widened tier or unions the two video sources depending on the verify predicate.
- The resulting grant is minted into the LiveKit JWT — the SDK client reads the same clamped or widened source list from the token.
audio_only; the gate only ever runs inside the audio-only path, and the
moderator’s widen decision is a per-participant call made on the room’s
transcript-cluster signal, not a configuration knob. An integrator never
“enables the gate” — they enable audio_only on the room, and the gate is
the only mechanism by which video comes back afterward.
4. Why widen can never promote to publish
The same non-widening invariant that the route layer’s per-source override enforces holds here: an allow-list can narrow a grant, never widen a subscribe-only one. Concretely:- A
viewerjoin with acanPublishSourcesoverride is returned unchanged — the override cannot convert them into a publisher. - A
viewerjoin verified by the transcript gate is likewise returned unchanged — the gate cannot convert them into a publisher either. - The gate only ever moves the two video sources in or out of an
already-publishing participant’s
canPublishSources. It is structurally incapable of flippingcan_publishfromfalsetotrue.
5. Two negative-test examples
The gate’s two hard negatives are what it is designed to guarantee: Audio-only with no transcript — nothing widens.panelist joins an audio_only: true room before any signed-speech
cluster converges. The gate’s clamp leaves them on the audio ceiling:
can_publish stays true, and the publication sources stay exactly
["microphone"]. Camera, screen-share, and screen-share-audio never appear.
They stay audio-only until verification.
Audio-only with a verified transcript — video, not publish.
panelist once the signed-speech cluster verifies them. The gate
unions camera and screen_share onto the audio sources — the
pre-verification microphone source is preserved — but can_publish was
already true; the gate added video sources, not publish capability. A
subscribe-only tier (viewer, hidden_supervisor, a lobby hold) run
through the same verified gate gets back its original grant unchanged: it
upgrades to video-only, never to publish.
Related
Video: rooms, embeds, recording, and broadcast
The channel-level page — room kinds, join tokens, the embed, recording,
moderation, and broadcast.
Video meetings and conferences
The ordered walkthrough — create a scheduled room, invite guests, run the
meeting end to end.
The video room model
Scheduled vs ad-hoc rooms, the created-to-closed lifecycle, and join-token
semantics this gate composes over.
Video room access tokens
Full token scope —
participant_tier, effective-grant read-back, and
expiry semantics.