独立 RTC 频道
im.channels 让已登录用户加入业务服务端创建的音视频频道,不要求好友关系或 IM 群。频道规则和开通条件见独立 RTC 频道。本轮频道 API 已提供源码,使用前确认安装版本含以下接口;SDK 制品发布与真机验收状态见平台与版本。
加入与采集
下面的 im 为已登录客户端,ticketFromBusinessServer 由你的业务服务端交付。开放频道省略 ticket。
if (!im.channels.supported) throw new Error('当前环境不支持频道媒体');
const cancelJoin = new AbortController();
const channel = await im.channels.join('meeting-demo', {
ticket: ticketFromBusinessServer,
signal: cancelJoin.signal,
});
const stopState = channel.subscribe(() => {
const snapshot = channel.getSnapshot();
console.log(snapshot.session.status, snapshot.media_state);
});
// 在用户点击采集按钮后调用;默认麦克风、摄像头关闭。
await channel.setMicrophoneEnabled(true);
// 仅 video 频道的 publisher 可以开启摄像头。
await channel.setCameraEnabled(true);
// 页面离开时:先取消订阅,再退出。
stopState();
await channel.leave();join 接受频道 ID 加选项,或包含 channel_id 的对象。选项为 ticket、client_session_id、signal、microphoneEnabled、cameraEnabled。SDK 自动生成加入键,同一次尝试重试不变;业务自行提供时也必须保持固定。准备重试、连接和入会确认共用首次期限。
加入仅在媒体已连接且服务端确认为 joined 后成功。cancelJoin.abort() 取消尚未完成的加入;已有句柄须调用 leave()。失败、超时或取消会收尾预留并停止本地媒体。
需要 HTTPS 或 localhost、WebRTC、麦克风 / 摄像头权限及媒体地址连通。采集和播放由用户交互触发,拒绝权限时可保持仅接收。subscriber 不能采集,audio 频道不能启用摄像头;supported 不代表应用已经开通或设备权限已经通过。
显示授权媒体
轨道事件使用 session_id 和 username 标识授权成员。不要将媒体 identity 当作用户名,也不要将 session ID 转为 JS number。
const container = document.querySelector('#channel-media')!;
const players = new Map<string, HTMLMediaElement>();
const offTrack = channel.on('track', ({ session_id, kind, track, local }) => {
if (local && kind === 'audio') return; // 避免播放本机麦克风回声。
const key = `${session_id}:${kind}`;
players.get(key)?.remove();
const player = document.createElement(kind === 'video' ? 'video' : 'audio');
player.autoplay = true;
player.muted = local;
if (player instanceof HTMLVideoElement) player.playsInline = true;
player.srcObject = new MediaStream([track]);
container.append(player);
players.set(key, player);
void player.play().catch(() => {
// 显示“点击播放”按钮,并在用户操作中再次调用 player.play()。
});
});
const offRemoved = channel.on('trackRemoved', ({ session_id, kind }) => {
const key = `${session_id}:${kind}`;
const player = players.get(key);
if (player) { player.srcObject = null; player.remove(); }
players.delete(key);
});
// 页面卸载时执行:
offTrack();
offRemoved();
for (const player of players.values()) { player.srcObject = null; player.remove(); }
players.clear();
await channel.leave();只有与 HTTP 已加入且确认媒体连接的成员精确匹配的轨道才会暴露。名单暂未确认、成员退出或授权撤销时,不应继续显示旧画面。
查询与恢复
| 方法 / 属性 | 含义 |
|---|---|
supported、current | 本环境媒体能力、本地当前句柄 |
getChannel(id) / get(id) | 查询可见频道 |
getCurrentSession() / currentSession() | 查询当前登录对应的服务端会话,无会话为 null |
listParticipants(id, page?) / members(id, page?) | 查询可见成员;实际需要有效频道会话 |
join(id, options?) | 新加入 |
resume({channel_id, session_id, signal?}) | 重连原会话,不重复预留席位,不自动开启采集 |
const existing = await im.channels.getCurrentSession();
if (existing && ['joining', 'joined'].includes(existing.status)) {
const restored = await im.channels.resume({
channel_id: existing.channel_id,
session_id: existing.session_id,
});
// 用户确认后才重新开启采集。
}不能跨登录会话恢复;leaving 等待收尾,left 已结束。票据、句柄和媒体 Token 不放入 localStorage 或日志。
状态、事件与收尾
getSnapshot() 包含 channel、session、members、media_state、error;用 subscribe 订阅变化。句柄还提供 refresh()、采集开关和 leave()。
| 句柄事件 | 载荷 |
|---|---|
track、trackRemoved | session_id、username、kind、track、local |
participantJoined、participantLeft | Participant |
sessionLeaving、sessionLeft | 本人 Session |
channelClosing、channelClosed | Channel |
connectionChanged | connecting / connected / reconnecting / disconnected |
客户端事件 channel.changed 用于本地当前句柄变化。React / Vue 的 useChannel 用法见框架绑定。
SDK 自动心跳和续发授权凭据;页面 pagehide / freeze、登出和客户端销毁会收尾。普通最小化不等于页面退出。业务仍应在路由卸载时主动 leave;即使退出 HTTP 失败,本地媒体也停止,服务器可能暂时仍保留清理占用。
只有发起加入的页面持有媒体。错误见频道错误码,不要因忙线、封禁或授权拒绝反复生成新加入键。
