Skip to main content

The video room model

Video is a first-class Orbit channel: a meeting joins an inbox conversation, triggers the same recording lifecycle as a call, and feeds the same analytics and QA stack as voice. This page explains the room model itself — how rooms are created, how they live and die, how participants get in, and where the observability surfaces hang off it. The endpoint-by-endpoint reference lives in the Video API reference; this page is the model those endpoints implement.

Scheduled versus ad-hoc rooms

A room is created scheduled or ad-hoc. The difference is a timed access window versus an open one. The split is structural, not cosmetic: a scheduled room carries an intent record that can recur across many sessions (a recurring meeting re-uses the same room row each time it convenes), while an ad-hoc room is the session itself. History lives in video_room_sessions — one row per realised room lifetime, scheduled or ad-hoc — so the “Recent rooms” panel and the retention sweep see both uniformly.
Room templates are the middle case: a saved configuration you instantiate either live or scheduled. A template has no session history of its own until it is instantiated.

Lifecycle: created → active → closed

A scheduled room moves a status workflow: pending → ready → live → ended. Ad-hoc rooms are live as soon as the first participant joins.
  • created — the room row exists, and the intent (if scheduled) is persisted. No media is running yet.
  • active (live) — at least one participant is in the room. For scheduled rooms the create-step auto-recording hook deliberately skips “future” rooms and arms on first join instead, because the media server reaps unjoined scheduled rooms.
  • closed (ended) — the room is closed when the host ends it, when the empty-room reap fires, or when a broadcast egress is stopped. The room_finished webhook persists the final state (max participants, join events, totals, recording IDs) into video_room_sessions. Closing is a host action, not a participant one.
A scheduled room can be reopened: reconvening a recurring meeting appends a new video_room_sessions row rather than mutating the intent. Retention is per-workspace and sweeps soft-then-hard-delete session rows after the retention window — the same scheduler that handles call recordings.

Join tokens

Joining a room returns an access token — a short-lived JWT scoped to one room and one identity. It is an SDK credential, passed to Room.connect(url, token); it is never an HTTP Authorization header. Two tiers matter in the response:
  • host token — the room creator’s join token (minted by the create endpoint as host_token).
  • participant token — minted by POST /video/rooms-scheduled/{id}/join for a named identity, or purchased by a guest who redeems an invite link via POST /video/invites/{inviteToken}/redeem.
Tokens expire (expires_in_seconds + an absolute expires_at); re-mint a fresh token for the same identity before expiry to avoid dropping mid-session. The response also carries the effective grant — a participant_tier (viewer, panelist, host, hidden_supervisor) plus permissions after any host downgrade or waiting-room clamp — which your client must respect before showing publish controls. The full flow, the exact connection call, and the guest-invite alternative live in Video room access tokens.

Recording and broadcast

Recording is opt-in per room (recording_enabled on the create body). Auto-start is deferred for scheduled-future rooms, and the egress handle is recorded on the session row when the room closes. Composite (one mixed room render) and per-participant track egress are separate paths — per-participant egresses are a fan-out, so they persist on the room’s settings rather than the session’s single recording columns. Broadcast egress is a separate discipline from in-room participation:
  • RTMP/HLS egress (POST /:id/egress/rtmp, POST /:id/egress/hls) pushes the live stream to a CDN or an external endpoint.
  • Broadcast viewers consume over HLS/WHEP through a CDN — they are not in-room participants. Their audience signal is each viewer player’s own heartbeat (POST /:name/heartbeat on /video/broadcast-viewership), maintaining a sliding-window concurrent-viewer count in Redis.
  • Registrants are the people who signed up before the room went live — check-in and approval/decision flows live on /video/rooms-scheduled/{id}/registrants. A registrant becomes an in-room participant only at join; a viewer may never join at all.
The Recording lifecycle page covers the egress lifecycle webhook family; the broadcast-viewership read path exists precisely because every other video analytic measures in-room participants and none counted the broadcast audience.

Analytics model

Three aggregates split video analytics by scope. Knowing which one to read avoids a cross-window fan-out:
  • Room usage (/video/room-usage-analytics) — org-level usage over time: sessions, peak/average concurrent participants, room-minutes, recording success rate, join failures. Answers “how is my org using video.” This aggregates video_room_sessions.
  • Engagement (POST/GET /rooms/:name/sessions/:sessionId/engagement) — per-session, per-participant: talk-time share, screen-share duration, hand-raises, merged dominant-speaker timeline. The host browser buffers active-speaker / screen-share / hand-raise signals during the meeting and flushes them at room-end — which keeps the hot ~10 Hz SFU speakers_changed webhook path write-free.
  • Chapter analytics (/video/chapter-analytics) — cross-recording theme aggregation: “Pricing objection”, “Demo walk-through” — per-theme average duration across a date window. Read-only; chapter rows are written by the chaptering pipeline on recordings.chapters.
Use room-usage for capacity and trend, engagement for comparing participants inside a session, and chapter analytics for recurring-theme analysis across recordings.

Live interpretation and captions

Live interpretation is the spoken interpreter channel — the audio analog of the translated caption line. A participant’s client posts one finalized caption utterance plus a target language to /video/live-interpretation, and the platform returns the spoken audio; captions/translate and this route both derive from the caption/STT pipeline, but one renders on-screen text while the other renders speech. Captions themselves are buffered by the host client during the meeting and flushed at room-end along with engagement — the same buffer-then-flush shape — so a post-meeting transcript and a post-meeting summary can be built without touching the hot SFU webhook.

Video QA scoring

QA scoring mirrors the voice coaching pipeline for the video pillar. The flow, on request for a session:
  1. Cache check on video_room_sessions.metadata.qa_score — a cached scorecard is returned unless regenerate is set.
  2. Resolve the session row (tenant-scoped; soft-deleted rows return NOT_FOUND).
  3. Resolve the transcript — transcript_override → metadata caption frames → persisted video_room_transcripts (same fall-through the post-meeting summary uses).
  4. Compute talk-balance deterministically from video_participant_engagement (no LLM): per-participant talk share plus a normalised-entropy balance score.
  5. Run an LLM judge over the redacted transcript (PII stripped first, mirroring voice QM scoring) to score compliance and per-dimension quality, and emit coaching tips.
  6. Persist the merged scorecard back into metadata.qa_score and return.
A pre-feature tenant degrades to has_data:false on the engagement read, never a 500, and the QA step itself never initiates outbound signalling — reporting only.

Diagram: scheduled versus ad-hoc

Video — channel overview

The channel-level page: what video meetings, webinars, and broadcasts do.

Video meetings — guide

How to schedule, join, invite guests, and run a meeting end to end.

Embed a video-consultation button

Put a “video call us” button on your own site — the embed consumes the same join-token flow.

Recording lifecycle

The egress lifecycle webhook family recordings land in.

Room access tokens

Full token scope, expiry, and guest-invite semantics.

Video API reference

The endpoint-by-endpoint contract this model is implemented by.