You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
开发指南
同一用户加入多个房间
复制全文
下载 pdf
同一用户加入多个房间

同一个用户可以加入多个房间,分别订阅和接收这些房间中的音视频流,并在其中一个房间中发布音视频。也可以发送和接收实时消息

适用场景

  • 大班小组课:主讲老师在大班房间内讲课,学生在该房间内听讲,同时可以在小组房间交流提问,并由助教老师答疑。
  • 游戏场景:玩家可以在已加入的小队房间内和其他小队成员进行语音互动,同时能收听到世界房间内的广播音频。
  • 会议场景:云端会议过程中,主持人可以发起分组讨论。参会者无需离开原先的会议,即可在各自小组中进行音视频互动,不同讨论组互不干扰。

前提条件

你已经集成 RTC SDK v3.43 或更新的版本,实现了基本的音视频通话。
支持多房间功能的 SDK 详见API 及回调

功能实现

在集成 RTC SDK,并完成业务逻辑代码时,你已发现,音视频引擎类和房间类两个常用的主调类有明显的功能区分:

  • 通过使用音视频引擎类的方法,你可以启动音视频采集,并进行相关设置(如切换摄像头等);
  • 通过房间类的方法,你可以在房间内发布/订阅流,并进行相关设置(如用户自身在房间内的可见性等)。

要让一个用户加入多个房间,可以通过一个音视频引擎实例,创建多个房间实例,并为这些实例设置不同的房间 ID。同一个用户在多个房间中,可以订阅在这些房间中发布的音视频流。
本文以加入两个房间为例,你可以按照相同流程,让用户加入更多房间。

以下时序图以 Android SDK 中的 API 名称为例。不同端的 SDK 中 API 或回调名称可能略有不同,以 API 及回调为准。

Image

1. 创建引擎类

创建和初始化一个音视频引擎类。

参考 构建 RTC 应用 获取详细步骤。

const list = [
  {
    "lang": "java",
    "text": `// APP_ID: 已经在控制台申请的app_id
    // engineEventHandler: 用于接收 RTCEngine 回调的接口实例
    EngineConfig config = new EngineConfig();
    config.appID = appId;
    config.context = applicationContext;
    rtcEngine = RTCEngine.createRTCEngine(config, engineEventHandler);`, 
    "selected": true,
  },
  {
    "lang": "swift",
    "text": `// kAppID: 已经在控制台申请的app_id
    let engineCfg = ByteRTCEngineConfig.init()
    engineCfg.appID = appId
    //私有参数,可以填空
    engineCfg.parameters = [:]
    //delegate: 用于接收 ByteRTCEngine 回调的接口实例
    self.rtcEngine = ByteRTCEngine.createRTCEngine(engineCfg, delegate: self)`,  
  },
  {
    "lang": "cpp",
    "text": `// app_id: 已经在控制台申请的app_id
// handler: 用于接收 RTCEngine 回调的接口实例
// parameters: 私有参数,可以填 nullptr
    bytertc::EngineConfig conf;
    conf.app_id = g_appid.c_str();
    engine = bytertc::IRTCEngine::createRTCEngine(conf, handler.get());
  },
]
return (<PreCodeTabs list={list} />);

2. 启动音视频采集

创建音视频引擎类后,你可以启动音视频采集,并设置渲染视图。

// 开启音视频采集
    rtcEngine.startAudioCapture();
    rtcEngine.startVideoCapture();

    // 设置本地渲染视图,支持 TextureView 和 SurfaceView
    private void setLocalRenderView() {
        VideoCanvas videoCanvas = new VideoCanvas();
        videoCanvas.renderView = localView;
        videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
        rtcEngine.setLocalVideoCanvas(videoCanvas);
    }

3. 创建房间实例

创建房间实例后,你可以加入房间发布和订阅音视频流。建议设置房间回调接口,以便监听房间和音视频流的状态回调。
继续调用 createRTCRoom 并传入不同房间 ID,以创建多个房间实例,并分别加入这些房间。

// 创建房间1
    rtcRoom1 = rtcEngine.createRTCRoom(roomID);
    rtcRoom1.setRTCRoomEventHandler(firstRoomEventHandler);
    
    // 创建房间2
    rtcRoom2 = rtcEngine.createRTCRoom(roomID);
    rtcRoom2.setRTCRoomEventHandler(secondRoomEventHandler);

4. 加入 RTC 房间

Image

  1. 加入每个房间时,默认自动订阅房间中的音视频流。
// 用户信息
    UserInfo userInfo = new UserInfo(localUid, "");
    // 房间1配置
    RTCRoomConfig room1Config = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_LIVE, true, true, true, true);
    // 加入房间
    rtcRoom1.joinRoom(room1token, userInfo, true, room1Config);

    // 房间2配置
    // 一个用户只能在一个房间中发布视频流。
    RTCRoomConfig room2Config = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_LIVE, false, false, true, true);
    // 加入房间
    rtcRoom2.joinRoom(room2token, userInfo, true, room2Config);
  1. 监听进房状态,处理进房失败。
public void onRoomStateChanged(String roomId, String uid, int state, String extraInfo) {
    if (state == 0) { //进房成功
    } else if (state == -1000) { //token错误
    } else {// .... 其他错误
    }
}
  1. 订阅端在接收到其他用户发布/取消发布音视频流回调时,设置渲染视图。

在收到远端用户的 onUserPublishVideoStream 或 onFirstRemoteVideoFrameDecoded 回调后,你需要调用 setRemoteVideoCanvas 设置远端视图以在通话中查看远端视频。建议您在 onFirstRemoteVideoFrameDecoded 回调中设置视频渲染,确保视频渲染在视频解码完成后进行,以避免卡顿。

const list = [
  {
    "lang": "java",
    "text": `
    @Override
    public void onFirstRemoteVideoFrameDecoded(String streamId, StreamInfo streamInfo, VideoFrameInfo frameInfo) {
        runOnUiThread(() -> {
            // 设置远端视频渲染视图
            VideoCanvas videoCanvas = new VideoCanvas();
            videoCanvas.renderView = firstRoomRemoteView;
            videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
            rtcEngine.setRemoteVideoCanvas(streamId, videoCanvas);
        });
    }

    @Override
    public void onUserPublishStreamVideo(String streamId, StreamInfo streamInfo, boolean isPublish) {
        if (!isPublish) {
            runOnUiThread(() -> {
                // 解除远端视频渲染视图绑定
                rtcEngine.setRemoteVideoCanvas(streamId, null);
            });
        }
    }`,
    "selected": true,
  },
  {
    "lang": "swift",
    "text": `// 远端用户发布流
    func rtcEngine(_ rtcEngine: ByteRTCEngine, onFirstRemoteVideoFrameDecoded streamId: String, info: ByteRTCStreamInfo, withFrameInfo: ByteRTCVideoFrameInfo) { 
        // 渲染远端用户
        DispatchQueue.main.async {
            // 设置远端用户视频渲染视图
            let canvas = ByteRTCVideoCanvas.init()
            canvas.view = view.videoView
            canvas.renderMode = .hidden
            self.rtcEngine?.setRemoteVideoCanvas(streamId, withCanvas: canvas);
        }
    }

    func rtcRoom(_ rtcRoom: ByteRTCRoom, onUserPublishStreamVideo streamId: String, info: ByteRTCStreamInfo, isPublish: Bool) {
        if !isPublish  {
        //移除 UI 显示
            DispatchQueue.main.async {
                let canvas = ByteRTCVideoCanvas.init()
                canvas.view = nil // 置为空
                canvas.renderMode = .hidden
                self.rtcEngine?.setRemoteVideoCanvas(streamId, withCanvas: canvas)
            }
        }
    }`, 
  },
  {
    "lang": "cpp",
    "text": `//远端用户发布流
void EngineHandler::onFirstRemoteVideoFrameDecoded(std::string streamId, bytertc::StreamInfo info, bytertc::VideoFrameInfo frameInfo) {
    bytertc::VideoCanvas canvas;
    canvas.view = (void*)ui->widget->winId();
    engine->setRemoteVideoCanvas(streamId.c_str(), canvas);
}

void RoomHandler::onUserPublishStreamVideo(std::string streamId, bytertc::StreamInfo info, bool publish)
    if (!publish) { //远端用户取消发布流
      bytertc::VideoCanvas cas;
      cas.view = nullptr;
      engine->setRemoteVideoCanvas(streamId.c_str(), cas);
    }
}
`, 
]
return (<PreCodeTabs list={list} />);

5. 离开 RTC 房间

用户结束通话时,退出各个房间,并销毁本地房间实例。

rtcRoom.leaveRoom();
    rtcRoom.destroy();
    rtcRoom = null;

6. 销毁引擎类

在销毁所有房间实例后可销毁音视频引擎。

RTCEngine.destroyRTCEngine();

示例项目

参考以下项目获取完整代码。在示例项目中,本端用户加入了两个不同的 RTC 房间。你可以按照相同流程,让用户加入更多房间。

API 及回调

你可以根据上文的描述和示例,使用以下客户端 SDK,在不同的端上实现同一用户加入多房间功能。

说明:表格中的 macOS API 接口为 Objective-C,而示例项目中的 macOS 项目使用的是 Windows SDK 中的 API 接口。

平台

Android

iOS

macOS

Windows

Linux

Electron

Flutter

Unity

音视频引擎类

RTCEngine

ByteRTCEngine

ByteRTCEngine

IRTCEngine

IRTCEngine

RTCVideo

RTCVideo

IRTCVideo

开启视频采集

startVideoCapture

startVideoCapture

startVideoCapture

startVideoCapture

startVideoCapture

startVideoCapture

startVideoCapture

StartVideoCapture

开始音频采集

startAudioCapture

startAudioCapture

startAudioCapture

startAudioCapture

startAudioCapture

startAudioCapture

startAudioCapture

StartAudioCapture

设置本地视图

setLocalVideoCanvas

setLocalVideoCanvas:

setLocalVideoCanvas:

setLocalVideoCanvas

setLocalVideoCanvas

setupLocalVideo

RTCViewContext

SetLocalVideoSink

创建房间

createRTCRoom

createRTCRoom:

createRTCRoom:

createRTCRoom

createRTCRoom

createRTCRoom

createRTCRoom

CreateRTCRoom

音视频房间类

RTCRoom

ByteRTCRoom

ByteRTCRoom

IRTCRoom

IRTCRoom

RTCRoom

RTCRoom

IRTCVideoRoom

设置房间回调

setRTCRoomEventHandler

setRTCRoomDelegate:

setRTCRoomDelegate:

setRTCRoomEventHandler

setRTCRoomEventHandler

setRTCRoomEventHandler

加入房间

joinRoom

joinRoom:userInfo:userVisibility:roomConfig:

joinRoom:userInfo:userVisibility:roomConfig:

joinRoom

joinRoom

joinRoom

joinRoom

JoinRoom

房间状态回调

onRoomStateChanged

rtcRoom:onRoomStateChanged:withUid:state:extraInfo:

rtcRoom:onRoomStateChanged:withUid:state:extraInfo:

onRoomStateChanged

onRoomStateChanged

onRoomStateChanged

onRoomStateChanged

OnRoomStateChangedEventHandler

发布或取消回调视频流

onUserPublishStreamVideo

rtcRoom:onUserPublishStreamVideo:info:isPublish:

rtcRoom:onUserPublishStreamVideo:info:isPublish:

onUserPublishStreamVideo

onUserPublishStreamVideo

onUserPublishStream

onUserPublishStream

OnUserPublishStreamEventHandler

离开房间

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

LeaveRoom

离开房间

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

leaveRoom

LeaveRoom

销毁房间

destroy

destroy

destroy

destroy

destroy

destroy

destroy

Destroy

销毁音视频引擎

destroyRTCEngine

destroyRTCEngine

destroyRTCEngine

destroyRTCEngine

destroyRTCEngine

destroyRTCVideo

destroy

Release

常见问题

Q1: 同一用户如何在多个房间内同时发送音视频流?

A:对于一个音视频引擎实例,即使加入了多个房间,也仅能同时在其中的一个房间中发布音视频流。如果需要在多个房间中同时发布音视频流,参看 跨房间转发媒体流

Q2: 如何处理 Token 相关错误?

A:确保每个房间的 token 使用了对应的 roomId 生成。更多 Token 相关问题,参见 Token 使用常见问题

最近更新时间:2026.06.15 21:04:36
这个页面对您有帮助吗?
有用
有用
无用
无用