Raven Live Streaming is not a third real-time system bolted onto RTC and
Chat — it's the two of them, composed. A live stream is one RTC Room
(the host and any co-hosts are just participants with publish
permission) plus one Chat Conversation (created and attached
automatically), with lifecycle and role bookkeeping layered on top. You
don't run a separate media server, a separate chat backend, or stitch
the two together yourself.
Why this matters
A typical live-streaming build asks you to run an SFU, a chat service,
and a bridge between the two — three systems, three sets of
credentials, three failure modes. On Raven, POST /v1/live-streams
gives you both a room and a conversation in one call, and a viewer's
chat message rides the same infrastructure @corvidhq/chat already
documents.
| RTC | Chat | Live Streaming | |
|---|---|---|---|
| Primitive | Room | Conversation | LiveStream (wraps one of each) |
| Who can publish | anyone with publish: true | — | only hosts/co-hosts — never viewers |
| Credential | RTC token | chat token | both, minted together per role |
Lifecycle
CREATED → STARTING → LIVE → ENDING → ENDED
In the current implementation, start() moves CREATED → LIVE
directly — there's no asynchronous provisioning step that would need a
visible STARTING phase, so the state is skipped rather than
paused-on. end() moves LIVE → ENDED and closes the underlying room.
ENDED is terminal: there is no restart or replay path in this phase.
Every other transition is rejected with RAVEN_STREAM_INVALID_STATE.
Roles
- Host — created the stream (or was added with the
HOSTrole). Can publish audio/video, invite/remove co-hosts, and moderates chat withADMINscope. - Co-host — added by a host. Can publish audio/video and moderates
chat with
MODERATORscope. - Viewer — anyone else. Subscribe-only, always: a viewer's RTC token
has
publish: falsebaked in server-side, and the viewer-token request has no role field to override it. Chats withMEMBERscope.
Raven's own ProjectMember/RBAC model is unrelated to any of this — it
controls who on your team can manage the Raven project itself. Hosts
and viewers are your application's end users, authenticated however
your backend already authenticates them, and are never granted
dashboard access.
Chat and reactions
Every stream gets a Conversation the moment it's created, plus a
hidden system root message. Regular chat (stream.chat.sendMessage)
works exactly as documented in Chat. Reactions
(stream.react('❤️')) add a Reaction to that root message — there's
no second, live-streaming-specific realtime primitive; it's the same
aggregation Reactions already provides for ordinary messages.
Webhooks
live_stream.created, .started, .ended, .host_joined,
.host_left, .viewer_joined, .viewer_left — signed and delivered
exactly like every other Raven webhook. See Webhooks.
Known limitations (this phase)
- No cloud recording or AI moderation/captions yet. Filters/effects are
already supported — see Filters & Effects —
since a stream's camera is an ordinary
@corvidhq/rtctrack. - Viewer count is derived live from the SFU's current participants, not stored — see Analytics for exactly what's tracked.
- No dashboard/CLI path to mint host or viewer credentials — by design; see SDK Support Matrix.
- Flutter's
raven_livepackage hasn't run against a real Flutter toolchain in this repo yet (no Flutter/Dart available in the build environment that wrote it) — the credential-parsing logic has unit tests, butRavenLiveStream.join()/leave()/react()haven't been exercised end-to-end. Treat it as unverified until a Flutter CI job covers it.
Next
- Quickstart
- Streams & Lifecycle
- Hosts & Co-hosts and Viewers
- Live Chat and Reactions
- SDK Support Matrix — what every SDK implements, and what's deliberately absent
Interactive hosts and co-hosts run on Raven RTC; comments and reactions run on Raven Chat — Live Streaming is what connects the two into one product surface, not a replacement for either.