Live Streaming lets one host broadcast video to many viewers. Viewers can't broadcast. They watch, chat, and send reactions. Think of a webinar, a live class, a product launch, or a creator going live to their followers.
Where this fits: you already have a project and an API key (API credentials). Your backend creates the stream and makes a credential for each person. Your app joins with that credential. Webhooks tell your backend when the stream starts, ends, and who joined.
How it's built
A live stream is not a separate system. It's two things you may already know, created together:
- one RTC room, where the video happens. The hosts are the participants who can publish (send camera and mic).
- one chat conversation, where viewers talk and react.
One call, POST /v1/live-streams, creates both. You don't run a media server
or a chat server, and you don't wire them together yourself.
| RTC | Chat | Live Streaming | |
|---|---|---|---|
| Main object | Room | Conversation | LiveStream (one room + one conversation) |
| Who can publish | Anyone your token allows (publish: true) | — | Only hosts and co-hosts. Never viewers. |
| Credential | RTC token | Chat token | Both, made together, per person |
New to words like publish, SFU, or token? See the Glossary.
What happens during a stream
Say alice runs a launch event and carol watches:
addHost(alice)start()createViewerToken(carol)end()All the steps in the left column run on your backend with your API key. The apps only ever receive a credential.
Lifecycle
A stream's status only moves forward:
CREATED → STARTING → LIVE → ENDING → ENDED
What actually happens today:
start()moves the stream fromCREATEDstraight toLIVE.STARTINGis skipped.end()moves it fromLIVEtoENDEDand closes the room. Everyone still connected is disconnected.ENDEDis final. You can't restart or replay a stream. For the next event, create a new stream.- Any other move fails with
RAVEN_STREAM_INVALID_STATE.
Details: Streams & lifecycle.
Roles
Every person in a stream has one of three roles. Your backend picks the role by which call it makes, not by a field the app sends:
| Role | Made by | Can publish video/audio | Chat scope | Typical person |
|---|---|---|---|---|
| Host | Creating the stream, or addHost with HOST | Yes | ADMIN | The presenter. |
| Co-host | addHost (the default role) | Yes | MODERATOR | A guest speaker or a second presenter. |
| Viewer | createViewerToken | Never | MEMBER | Everyone in the audience. |
A viewer's RTC token always has publish: false. The viewer-token request
has no role field, so a viewer can't ask for more.
Free tier
Live Streaming has its own free allowance. It's separate from RTC minutes and chat messages, so using one never uses up another.
- 100 host-hours per account.
- Counted from the time hosts and co-hosts are actually connected. Gaps while reconnecting don't count.
- Each host counts on their own. Two co-hosts streaming for one hour = 2 host-hours.
- Viewers are free. They never use host-hours or RTC minutes, no matter how many there are or how long they watch.
There are also three limits:
| Limit | Default | What happens when you hit it |
|---|---|---|
| Live streams at once | 1 per account (across all projects and environments) | Starting a second stream fails with 403 RAVEN_STREAM_CONCURRENCY_LIMIT_EXCEEDED until the first one ends. |
| Viewers per stream | 100 | The 101st viewer token fails with 403 RAVEN_STREAM_VIEWER_LIMIT_EXCEEDED. |
| Stream length | 240 minutes | The stream ends automatically. |
So on the free tier, plan for one event at a time, up to 100 viewers, up to 4 hours long. A paid plan lifts these limits. Full details: Usage.
Chat and reactions
- Every stream gets a chat conversation as soon as it's created. You don't create it yourself.
stream.chat.sendMessageworks just like normal Chat.stream.react('❤️')adds a reaction to a hidden first message in that conversation. It's the same reactions feature chat already has, so many hearts from many viewers add up to one count.
Webhooks
Your backend can be told about these events, for example to post "We're live!" to social media, or to log who attended:
live_stream.created, .started, .ended, .host_joined, .host_left,
.viewer_joined, .viewer_left, plus .restream_active/.restream_failed
and .ingress_connected/.ingress_disconnected/.ingress_failed if you use
restream or encoder ingest.
They're signed and delivered like every other Livqeno webhook. See Webhooks and Stream events.
Not available yet
- No cloud recording.
- No AI moderation or captions.
- The viewer count is live only, with no history. See Analytics.
- You can't make host or viewer credentials from the dashboard or CLI. This is on purpose. See SDK support.
- Flutter's
livqeno_livepackage isn't fully tested yet. Its credential parsing has unit tests, butLivqenoLiveStream.join(),leave()andreact()haven't been tested end to end. Treat it as unverified.
Next steps
- Quickstart: run a full stream, host and viewer, in two browser tabs.
- Streams & lifecycle: create, start, update, and end streams from your backend.
- Hosts & co-hosts and Viewers: give each person the right credential.
- Live chat and Reactions: make the audience part of the show.
- SDK support: check what your platform can do.
- Restream and OBS & encoder ingest: send the stream on to YouTube or Twitch, or broadcast into it from OBS.
Video runs on Livqeno RTC. Comments and reactions run on Livqeno Chat. Live Streaming connects the two.