獨立 RTC 頻道
獨立頻道用於會議、語音房這類不依賴 IM 群的場景:使用者憑業務服務端給的許可加入,沒有振鈴和來電介面。Flutter 中用 im.channels 加入和離開,音影片由 deeprespond_im_call 包(LiveKit)提供,支援 Android 和 iOS。iOS 原生 App 目前沒有單獨的 Swift SDK,請透過 Flutter 接入。頻道的建立和授權見服務端的頻道概述。
| 要做什麼 | 看哪裡 |
|---|---|
| 引入包、申請許可權 | 依賴與許可權 |
| 加入、離開,顯示狀態和影片 | 加入與退出 |
| App 重啟後恢復 | API 與恢復 |
| 影片元件、退出登入和後臺時的行為 | 影片元件與生命週期 |
依賴與許可權
- 使用同一版本、且包含頻道介面的
deeprespond_im、deeprespond_im_flutter、deeprespond_im_call。deeprespond_im_call在建立客戶端時自動提供音影片能力,不需要設定DRClientOptions.call。 - 先按初始化建立客戶端
im並登入。 - iOS 在
Info.plist中加入NSMicrophoneUsageDescription和NSCameraUsageDescription;Android 宣告並申請麥克風、攝像頭許可權。 - 加入時預設不開啟麥克風和攝像頭;使用者拒絕許可權時,仍然可以只看、只聽。
- 只能觀看的身份(
subscriber)不能釋出音影片,純語音訊道(audio)不能開啟攝像頭。
加入與退出
dart
import 'package:deeprespond_im_flutter/deeprespond_im_flutter.dart';
import 'package:deeprespond_im_call/deeprespond_im_call.dart';
if (!im.channels.supported) throw StateError('当前环境没有频道媒体适配');
final cancel = DRCancelToken();
final channel = await im.channels.join('meeting-demo',
options: ChannelJoinOptions(ticket: ticketFromBusinessServer, cancel: cancel),
);
// join 成功表示媒体连接与 HTTP joined 确认完成。
await channel.setMicrophoneEnabled(true); // 在用户点击后调用。
await channel.setCameraEnabled(true); // 仅 video publisher。
final states = channel.stream.listen((snapshot) {
print(snapshot.session.status);
});
final tracks = channel.tracks.listen((items) {
// 完整的已授权轨道列表;sessionId 保持 String。
});
final localVideo = channel.localView();
// 实际远端 ID 来自授权 ChannelTrack.sessionId:
final remoteVideo = channel.remoteView(remoteSessionId);
await states.cancel();
await tracks.cancel();
await channel.leave();ticketFromBusinessServer來自業務服務端返回的加入許可,remoteSessionId來自軌道;不要把許可寫進日誌。開放頻道不需要ticket。- 還沒完成的
join用cancel.cancel()取消;拿到控制代碼之後用leave()離開。 - 加入失敗或連線晚到時,SDK 都會清理音影片;
leave的請求即使失敗,本地的麥克風和攝像頭也會停止。
API 與恢復
| API | 說明 |
|---|---|
supported、current | 這臺裝置有沒有音影片能力;本機當前的頻道控制代碼 |
getChannel(channelId) | 查詢頻道 |
getCurrentSession() | 本次登入在頻道中的會話,沒有時為 null |
listParticipants(channelId, cursor:, limit:) | 當前的成員;要求自己在這個頻道中 |
join(channelId, options:) | 加入,預設不開啟麥克風和攝像頭 |
resume(channelId:, sessionId:, cancel:) | 恢復原來的會話,不會重新佔用名額 |
dart
final existing = await im.channels.getCurrentSession();
if (existing != null && ['joining', 'joined'].contains(existing.status)) {
final restored = await im.channels.resume(
channelId: existing.channelId, sessionId: existing.sessionId,
);
// 用户确认后才重新开启采集。
}- 頻道控制代碼有
channelId、sessionId、snapshot、stream、tracks、currentTracks、refresh()、setMicrophoneEnabled()、setCameraEnabled()、leave()。 - 訂閱
stream和tracks時會先收到一次當前的值。 ChannelSnapshot包含channel、session、members、mediaState、error。- 本機的當前頻道變化時,客戶端發出
ChannelChanged事件。
影片元件與生命週期
ChannelVideoView(channel:, local:, sessionId:, fit:, placeholder:)顯示本地或指定會話的影片;控制代碼上還有localView()、remoteView(sessionId)、switchCamera()、setSpeakerphoneOn()。- SDK 只提供確認屬於有權加入的成員的軌道。
- 移除影片元件只是不再顯示;離開頁面時仍要呼叫
leave()。 - SDK 自動傳送心跳、續期加入許可,並處理退出登入、切換登入、被拒絕和會話到期。換了 IM 登入後不能恢復原來的會話。
- 每次加入都由服務端檢查許可權;媒體連線自身的令牌重新整理不代表許可權一直有效。
- 頻道不使用 CallKit 和系統來電介面,沒有來電通知。
- 要在後臺持續採集音影片,需要前臺服務、iOS 的後臺音訊等額外開發和測試。
頻道目前只提供原始碼:還沒有釋出包含頻道的版本,也還沒有在真實裝置上測試多人通話。
