Standalone RTC channels
Standalone RTC channels are for multi-party audio and video that doesn't depend on an IM group: business meetings, voice rooms, ad-hoc collaboration. Your server creates a channel with its own channel_id, and users join after signing in, with no need to be friends or in a group. Members have one of two roles: publishers (publisher) can turn on their microphone and camera, subscribers (subscriber) can only watch and listen.
A ticket-protected video meeting, from creation to a user joining:
# 1. 你的服务端:创建频道(默认需要票据、成员默认为发布者)
curl -X PUT "$IM_API/$ORG/$APP/rtc/channels/meeting-demo" \
-H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"项目会议","media":"video"}'
# 2. 你的服务端:给 alice 签发一次性票据,响应中的 tickets[0].ticket 经你的业务接口交给她
curl -X POST "$IM_API/$ORG/$APP/rtc/channels/meeting-demo/tickets" \
-H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
-d '{"users":[{"username":"alice","role":"publisher"}]}'
# 3. alice 的客户端:登录 IM 后,用客户端 SDK 带上票据加入频道For full client code, see Channel quickstart.
| You want to | See |
|---|---|
| Create, change or close channels | Channel management |
| Let specific users in | Channel tickets |
| See who's in a channel, remove or ban someone | Channel sessions and members |
| Implement joining and heartbeats in your own client without the SDK | Client channel sessions |
| Check channel usage | Channel usage and corrections |
| Know limits on participants, duration and so on | Limits |
| View and manage channels in the console | Console guide |
Requirements:
- The app has audio and video turned on (runtime policy
rtc_enabled), and both the platform's channel switch and the app's channel switch are on. The app's channel switch is on by default, and the platform can turn it off for a specific app; - The app is in good standing, and the concurrency quota and media service are available;
- Once new billing is enabled, the app's audio/video balance is positive; before switching to new billing, the plan's permissions apply.
Clients read rtc_channels_enabled and rtc_channels_protocol_version (currently 1) from the runtime config, and check the SDK's channels.supported, to decide whether to show a channel entry.
Choosing calls or channels
| One-to-one / group calls | Standalone channels | |
|---|---|---|
| Identifier | call_id; group calls are tied to a group_id | The channel_id your server chooses |
| How to enter | Call, ring, answer, or join the group's ongoing call | Join an open channel directly, or join with a one-time ticket issued to you |
| Who can enter | One-to-one rules or group membership | Signed-in users of the app, checked against tickets and channel bans |
| Who can speak | All participants | Only publisher; subscriber only receives |
| IM records | Can leave call records in one-to-one and group chats | No groups, conversation messages or call records |
| How clients control it | Call signaling and client APIs | HTTP APIs to join, heartbeat, renew credentials and leave; notifications only speed up state refreshes |
Channels only carry audio and video: no chat messages, call invitations, system ringing, screen sharing or media data messages. For text interaction, use IM messages or chat rooms alongside.
Integration steps
- In the console, confirm the app's audio and video is available and the platform's channel switch is on. Apps never configured individually have channels on by default.
- Your server creates a channel with the App Token, choosing the media type (
audioorvideo) and access mode. - For
ticketchannels, your server issues tickets for specific users, then hands each to its user through your own business API. - The user signs in to IM in the client SDK, checks capabilities and joins. Microphone and camera are off by default and turned on by the user.
- The SDK returns a channel handle only after media connects and the server confirms the user has joined. Leave the channel when the user leaves the page.
Keep the App Token on your server only. Channel tickets only grant entry to a channel and can't replace IM sign-in credentials.
Access modes and roles
| Value | Meaning |
|---|---|
open | Any signed-in user of the app can join, without (and can't submit) a ticket. The role is the channel's default_role; app status, channel bans and the concurrency quota still apply |
ticket | The default. A one-time ticket is required, bound to one user of the app, this channel and a role. Knowing a username, channel ID or media room name can't get around it |
publisher | Can publish microphone audio, and camera video in video channels |
subscriber | Can only receive. Roles are decided by the server: a publisher who turns off mic and camera is still a publisher |
audiochannels don't allow cameras.- In a
videochannel with the camera off, daily usage still counts as video; billed standard duration is graded by the video streams received, and counts at the audio tier when no video is received. - Media type, access mode, default role and participant limit can't be changed after creation.
Lifecycle and occupancy
Channel status: open → closing → closed. After closing or expiring, nobody can join, existing members start leaving, and the channel becomes closed once media resources are fully reclaimed. Channel IDs are case-sensitive and can't be reused after closing.
Member sessions: each time a user joins, a session_id is created, with status joining → joined → leaving → left. A joining session already holds a seat; a leaving session may still hold a seat and concurrency quota, and a new join request can't get around reclamation.
Only one place at a time:
- A user can only be in one call or one channel at a time; their other signed-in devices can't join at the same time.
- Channels and calls share the app's concurrent call quota: ongoing calls and channels with media activity count together, and a channel takes one unit no matter how many people are in it.
- When a channel is empty, its media room is reclaimed, but the channel itself stays open and can be joined later.
Headcount:
| Field | Meaning |
|---|---|
seat_count | Seats taken, including members joining or leaving |
joined_count | Media-connected headcount as last confirmed |
When media_state is unknown, the server temporarily can't confirm media state and joined_count is the last confirmed number; don't show it as an exact live count. A member's media_connected being null likewise means it can't be confirmed for now.
Platforms and release status
| Platform | Channel capabilities |
|---|---|
| Web / React / Vue | Join channels with audio and video, subscribe to channel state |
| Android | Kotlin / Java API, LiveKit adapter and video views |
| Flutter / iOS | Flutter LiveKit integration and video widgets; iOS through the Flutter plugin |
| Tauri | Media runs in the UI window, depending on the actual WebView and device permissions |
| UniApp H5 | A dedicated H5 entry reusing the Web SDK; verify directly with the repository demo |
| WeChat Mini Program | Only querying channels, your own session and members; can't join with audio and video |
| UniApp App (Android / iOS) | UTS native bridge available; verify on real devices on the channel page of the App Demo; no standalone Swift SDK yet |
These capabilities are implemented in source and have passed some automated checks, but no SDK release containing them has shipped yet; real-device interoperability and continuous background capture are still being verified. Use an SDK version that includes the channel API: older SDKs won't support channels just because the server has them on.
