为方便用户同时加入多个频道,接收多个频道的音视频流,Agora RTC Native SDK 3.0 及以上版本支持多频道管理,且频道数量无限制。
该功能可应用于类似超级小班课的场景:将一个互动大班里的学生分到不同的小班,学生可以在小班内进行实时音视频互动。根据场景需要,你还可以给每个小班可以配备一名助教老师。
我们在 GitHub 提供两个实现了多频道功能的开源示例项目,你可以前往下载体验,参考源代码。
SDK 提供 IChannel
类和 IChannelEventHandler
类实现多频道控制。
你可以多次调用 createChannel
,通过不同的 channelId
创建多个 IChannel
对象(对应多个频道),然后分别调用 IChannel
中的 joinChannel
方法加入对应的频道。
实现多频道功能的主要步骤如下:
createAgoraRtcEngine
和 initialize
方法,创建并初始化 IRtcEngine
。setChannelProfile
方法,将频道场景设置为直播。createChannel
方法,通过 channelId
创建一个 IChannel
对象。IChannel
类的 setChannelEventHandler
方法,接收该频道的回调通知。IChannel
类的 joinChannel
方法加入频道。IRtcEngine
类的频道中发布本地流:调用 IRtcEngine
类的 setClientRole
方法将用户角色设置为主播,然后调用 joinChannel
方法加入频道,SDK 会自动发布流。这种方式适用于只需要将本地流固定发布到 IRtcEngine
类的频道的场景。IChannel
类的频道中发布本地流:调用 IChannel
类的 setClientRole
方法将用户角色设置为主播,然后调用 publish
方法在该频道内发布流。这种方式适用于需要切换发流的频道的场景。IChannel
类中调用 publish
方法之前,必须先调用 setClientRole
将用户角色设置为主播。IChannel
类的频道中发布本地流,在切换发流频道前必须先调用 unpublish
取消当前的发布。加入多个频道,且在 IRtcEngine
类的频道中发布本地流的 API 时序如下:
加入多个频道,且在 IChannel
类的频道中发布本地流的 API 时序如下:
下面的示例代码演示了如何加入一个 IRtcEngine
类的频道和一个 IChannel
类的频道,且在 IRtcEngine
类的频道中发布本地流。
创建并初始化 IRtcEngine
对象。
m_rtcEngine = createAgoraRtcEngine();
RtcEngineContext context;
std::string strAppID = GET_APP_ID;
context.appId = strAppID.c_str();
m_eventHandler.SetMsgReceiver(m_hWnd);
context.eventHandler = &m_eventHandler;
int ret = m_rtcEngine->initialize(context);
启用视频模块。
m_rtcEngine->enableVideo();
将频道场景设置为直播场景。
m_rtcEngine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING);
设置用户角色为主播。
m_rtcEngine->setClientRole(CLIENT_ROLE_BROADCASTER);
传入 token
和 channelId
, 加入 IRtcEngine
对象的频道。加入 IRtcEngine
类的频道后,SDK 会自动发布本地流。
m_rtcEngine->joinChannel(APP_TOKEN, ChannelId, "", 0);
创建并获取一个 IChannel
对象,并监听该频道的回调通知。
IChannel * pChannel = static_cast<IRtcEngine2 *>(m_rtcEngine)->createChannel(szChannelId.c_str());
ChannelEventHandler* pEvt = new ChannelEventHandler;
pEvt->setMsgHandler(GetSafeHwnd());
m_channels.emplace_back(szChannelId, pChannel, pEvt);
pChannel->setChannelEventHandler(pEvt);
加入 IChannel
对象对应的频道。加入频道后,SDK 会自动订阅音视频流。
pChannel->joinChannel(APP_TOKEN, "", 0, options);
离开并销毁 IChannel
对象的频道。
pChannel->leaveChannel();
pChannel->release();
离开 IRtcEngine
对象的频道,并销毁 IRtcEngine
对象。
m_rtcEngine->leaveChannel();
m_rtcEngine->release(true);
如果在加入 IChannel
类的频道时,将媒体订阅选项设置为不自动订阅音频流或视频流,加入频道后,muteRemoteAudioStream
或 muteRemoteVideoStream
方法会失效。
IChannel
中的 joinChannel
方法中提供媒体订阅选项设置(autoSubscribeAudio
和 autoSubscribeVideo
),可以控制在加入频道后是否自动订阅音频流和视频流,默认为自动订阅。如果你需要在加入 IChannel
的频道时仅接收指定用户的音频流或视频流,Agora 建议使用以下方法:
IChannel
中的 setDefaultMuteAllRemoteAudioStreams(true)
或 setDefaultMuteAllRemoteVideoStreams(true)
设置默认不接收该频道的所有音频流或所有视频流。IChannel
中的 joinChannel
加入频道(媒体订阅选项使用默认设置)。IChannel
中的 muteRemoteAudioStream(false)
或 muteRemoteVideoStream(false)
接收指定用户的音频流或视频流。在视频场景中,如果远端用户是通过 IChannel
加入频道的,那么在设置远端视图时,还需要在 VideoCanvas 中指定该远端用户所在频道的 channel ID,否则会无法渲染出远端视频画面。
SDK 仅支持用户同一时间在一个频道内发布媒体流。因此只要你在一个频道内正在发布流,就无法在另一个频道发布。
由于通过 IRtcEngine
类和 IChannel
类下的 joinChannel
方法加入频道后,SDK 的默认行为有以下差异:
IRtcEngine
类下,SDK 默认发布本地音视频流到本频道。IChannel
类下,SDK 默认不发布本地音视频流到本频道。因此,以下操作会导致 SDK 返回 ERR_REFUSED(5)
错误码:
通过 IChannel
类加入多频道:
publish
方法后,未调用频道一的 unpublish
方法结束发布,就调用频道二的 publish
方法。通过混用 IRtcEngine
类和 IChannel
类加入多频道:
IRtcEngine
类加入频道一,然后通过 IChannel
类加入频道二后,试图调用 IChannel
类的 publish
方法。IChannel
类的 publish
方法。IChannel
类的 publish
方法后,未调用对应 IChannel
类的 unpublish
方法,就试图通过 IRtcEngine
类的 joinChannel
方法加入频道。