Roles, Channel Profiles and Live Streaming
communication/live profiles, host/audience roles, privilege bits, role switching and audience behaviour.
RTC has two orthogonal dimensions: the channel profile (communication / live) decides "who is talking", and the role (host / audience) decides "who may publish". This page explains both, and what the SDK and the server each do when they change.
Prerequisites
- A project is created and token authentication works; the
rolein the token sets the initial role. - The channel profile (communication or live) is chosen; the profile does not change during the channel lifetime.
Channel profile
| Profile | Semantics | Typical use |
|---|---|---|
communication | Everyone is a peer and may publish by default | Meetings, customer support, 1v1 |
live (liveBroadcasting) | The host publishes, the audience can only subscribe; roles apply | Live streaming, large classes, co-hosting |
The profile is decided when joining: on the web you pick the mode with createClient({ mode: 'rtc' }), on native platforms you call setChannelProfile(...) before joining. The profile cannot be switched mid-call — rejoin to change it.
Roles
| Role | Privilege bits | May publish | May subscribe |
|---|---|---|---|
host (broadcaster) | join_channel publish_audio publish_video publish_data subscribe | ✅ | ✅ |
audience | join_channel subscribe | ❌ | ✅ |
The authorization basis for a role is the privilege bits in the token (see AccessToken2 semantics), not what the client declares about itself. So "the UI prevents the audience from publishing" is only user experience; what actually blocks privilege escalation is the absence of publish_* in priv.
Switching roles on the client
// Switch to audience: the SDK stops local publishing (without destroying the tracks) and stops subscribing to video to save bandwidth
await client.setClientRole('audience');
// Switch back to host: local tracks must be published again
await client.setClientRole('host');
await client.publish([microphoneTrack, cameraTrack]);The overload with options lets you pick the audience latency tier (low latency vs bandwidth saving):
await client.setClientRole('audience', { level: 2 });Role changes are announced to other participants through user-info-updated(uid, 'role'); the server side can also force a role change, see POST /v1/channels/{channelName}/users/{uid}/role in Channel management.
Forcing a role change from the server
Not every scenario should be decided by the client: promoting or demoting a host is usually decided by your backend (only paying users may take the mic, for example). After the server-side endpoint changes a role:
- That user's privileges take effect at the next token validation or renewal;
- Established connections receive a role-change notification;
- Outside a renewal window the client must call
renewTokenitself or reconnect — the troubleshooting manual has a comparison table for this.
Three common pitfalls in live scenarios
| Pitfall | Symptom | Correct approach |
|---|---|---|
| The audience keeps subscribing to video | Downlink bandwidth explodes as the audience grows | Use the audience role and subscribe only to the uids you need |
| No republish after a role switch | Other participants cannot see the user after promotion to host | After setClientRole('host') you must call publish again |
Using mode: 'live' but forgetting to set a role | The default role may not be the one you want | Call setClientRole explicitly and issue the matching privilege bits in the token |
Combining with live streaming and recording
- To push to a CDN: use Media Push (
rtmp-converters), not a direct push from the client; - To record: use Cloud recording; with
mode=compositethe streams are mixed according to the layout; - Low latency for the audience: use the "audience latency tier" together with dual-stream/simulcast (see Stream control and fallback).
Boundary with IM
"Who is the host" is usually decided by IM signalling in a real product. Our division of labour is: IM negotiates the business role, RTC authorizes the media. The two are aligned through token privilege bits — IM says "you are the host now", your backend issues a token with host privileges, and the client calls renewToken.
Next steps
- REST API reference: complete endpoints, parameters and curl.
- Error codes: locate failures by
code/ HTTP status. - FAQ: quotas, limits and troubleshooting.