nimeet Docs
中文

Roles, Channel Profiles and Live Streaming

communication/live profiles, host/audience roles, privilege bits, role switching and audience behaviour.

Version v1.1.0 · Updated 2026-10-26 · revision 1

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 role in 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

ProfileSemanticsTypical use
communicationEveryone is a peer and may publish by defaultMeetings, customer support, 1v1
live (liveBroadcasting)The host publishes, the audience can only subscribe; roles applyLive 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

RolePrivilege bitsMay publishMay subscribe
host (broadcaster)join_channel publish_audio publish_video publish_data subscribe✅✅
audiencejoin_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

javascript
// 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):

javascript
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:

  1. That user's privileges take effect at the next token validation or renewal;
  2. Established connections receive a role-change notification;
  3. Outside a renewal window the client must call renewToken itself or reconnect — the troubleshooting manual has a comparison table for this.

Three common pitfalls in live scenarios

PitfallSymptomCorrect approach
The audience keeps subscribing to videoDownlink bandwidth explodes as the audience growsUse the audience role and subscribe only to the uids you need
No republish after a role switchOther participants cannot see the user after promotion to hostAfter setClientRole('host') you must call publish again
Using mode: 'live' but forgetting to set a roleThe default role may not be the one you wantCall 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=composite the 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

Generated by the documentation build pipeline · 2026-10-31 01:24:02 UTC · Documentation center v1.1.0.

Content follows the public API definitions.

ni-meet is a self-hosted RTC PaaS with a LiveKit-based media plane (Apache-2.0) and an Agora-compatible API.