更新时间: 2021-04-01

# 跨房间连麦

  1. 跨房间连麦前需要双方都已经加入自己的主房间,未加入主房间前无法进行连麦的邀请和被邀请。
  2. 跨房间连麦功能中区分主房间和副房间,其中:主房间就是本端在最开始加入的房间,即:RCRTCRoom (opens new window),副房间是在接受邀请后加入的对方房间,即:RCRTCOtherRoom (opens new window)
  3. 两种房间的类都有对应的代理 IRCRTCRoomEventsListener (opens new window)IRCRTCOtherRoomEventsListener (opens new window) 用来区分不同类型房间的回调。

# 体验 Demo

集成 Demo 示例

融云在 GitHub 上提供了跨房间连麦快速集成 Demo quickdemo-pk (opens new window) 代码示例,方便开发者参考。

# 主流程

# 发起邀请

向指定用户发送跨房间连麦请求,使用加入房间成功回调返回的RCRTCRoom类获取RCRTCLocalUser对象,调用

输入参数说明

参数 类型 说明
inviteeRoomId String 被邀请者所在房间 id
inviteeUserId String 被邀请用户 id
inviterAutoMix boolean 是否将邀请者音视频资源发送到被邀请人房间中合流
extra String 扩展字段,默认为空
callback IRCRTCResultCallback 发送回调

回调参数说明

onFailed 说明:

回调参数 回调类型 说明
errorCode RTCErrorCode (opens new window) 音视频状态码

代码示例

    /**
     * 向指定用户发送跨房间连麦请求
     * <P>
     * 1: inviterAutoMix为true时:
     *
     * 1.1:如果被邀请方在加入邀请方房间之前发布了资源,当被邀请方加入邀请者房间成功后,服务器会把被邀请方流资源合并到邀请方视图 ·(默认仅悬浮布局合流)上。
     *
     * 1.2:如果被邀请方在加入邀请方房间之前没有发布过资源,将会在被邀请方发布资源成功后,服务器会把被邀请方流资源合并到邀请方视图(默认仅悬浮布局合流)上。
     *
     * 2:无论为true或false,双方都可以使用{@link RCRTCLiveInfo#setMixConfig(RCRTCMixConfig, IRCRTCResultCallback)} 方法主动设置合流布局。一旦主动设置过合流布局,后续音视频直播过程中设置的自动合流参数将失效。
     * <P/>
     */
RCRTCRoom.getLocalUser().requestJoinOtherRoom(inviteeRoomId, inviteeUserId, inviterAutoMix, "extra", new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {

    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {

    }
});
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 取消邀请

取消正在进行中的跨房间连麦请求

输入参数说明

参数 类型 说明
inviteeRoomId String 被邀请者所在房间 id
inviteeUserId String 被邀请者用户 id
extra String 扩展字段,默认为空
callback IRCRTCResultCallback 发送回调

回调参数说明

onFailed 说明:

回调参数 回调类型 说明
errorCode RTCErrorCode (opens new window) 音视频状态码

代码示例

RCRTCRoom.getLocalUser().cancelRequestJoinOtherRoom(inviteeRoomId, inviteeUserId, "extra", new IRCRTCResultCallback() {
     @Override
     public void onSuccess() {
         
     }

     @Override
     public void onFailed(RTCErrorCode errorCode) {
        
     }
 });
已复制
1
2
3
4
5
6
7
8
9
10
11

# 应答邀请

响应跨房间连麦请求

输入参数说明

参数 类型 说明
inviterRoomId String 邀请者所在房间 id
inviterUserId String 邀请者用户 id
agree boolean 被邀请者是否同意连麦邀请
inviteeAutoMix boolean 是否将被邀请者音视频资源发送到邀请人房间中合流
extra String 扩展字段,默认为空
callback IRCRTCResultCallback 发送回调

回调参数说明

onFailed 说明:

回调参数 回调类型 说明
errorCode RTCErrorCode (opens new window) 音视频状态码

代码示例

    /**
     * <P>
     * 1:inviteeAutoMix 为true时:
     *
     * 1.1:如果邀请方在发送连麦请求之前发布了资源,当被邀请方加入邀请者房间成功后,服务器会把邀请方流资源合并到被邀请方视图(默认仅悬浮布局合流)上。
     *
     * 1.2:如果邀请方在发送连麦请求之前没有发布资源,将会在邀请方发布资源成功后,服务器才会把邀请方的资源合并到被邀请方视图(默认仅悬浮布局合流)上。
     *
     * 2: 无论为true或false,双方都可以使用{@link RCRTCLiveInfo#setMixConfig(RCRTCMixConfig, IRCRTCResultCallback)} 方法主动设置合流布局。一旦主动设置过合流布局,后续音视频直播过程中设置的自动合流参数将失效。
     *
     * <P/>
     */
RCRTCRoom.getLocalUser().responseJoinOtherRoom(inviterRoomId, inviterUserId, agree, inviteeAutoMix, "extra", new IRCRTCResultCallback() {
@Override
public void onSuccess() {
   
 }

@Override
   public void onFailed(RTCErrorCode errorCode) {
       
   }
});
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 加入副房间

连麦邀请后加入副房间

输入参数说明

参数 类型 说明
roomId String 房间 ID ,长度 64 个字符,可包含:A-Za-z0-9+=-_
callBack IRCRTCResultDataCallback<RCRTCOtherRoom> 加入房间回调

回调参数说明

onSuccess 说明:

回调参数 回调类型 说明
room RCRTCOtherRoom (opens new window) 其他房间类对象,提供注册房间事件通知的接口

onFailed 说明:

回调参数 回调类型 说明
errorCode RTCErrorCode (opens new window) 音视频错误码

代码示例

RCRTCEngine.getInstance().joinOtherRoom(roomId, new IRCRTCResultDataCallback<RCRTCOtherRoom>() {
  @Override
  public void onSuccess(RCRTCOtherRoom rcrtcOtherRoom) {
      
  }

  @Override
  public void onFailed(RTCErrorCode rtcErrorCode) {
      
  }
});
已复制
1
2
3
4
5
6
7
8
9
10
11

# 注册其他房间事件监听

  1. 使用加入其他房间成功后返回的 RCRTCOtherRoom 对象注册房间事件监听 RCRTCOtherRoom.registerOtherRoomEventsListener(IRCRTCOtherRoomEventsListener var1) (opens new window) ,有用户加入、离开、发布资源后会触发此监听回调,在回调中订阅用户音视频资源,可进行音视频通话。
  2. 在不使用或退出房间之前取消注册RCRTCOtherRoom.unregisterOtherRoomEventsListener
RCRTCOtherRoom.registerOtherRoomEventsListener(new IRCRTCOtherRoomEventsListener() {

                            /**
                             * 其他房间内用户发布资源
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             * @param list 发布的资源
                             */
                            @Override
                            public void onRemoteUserPublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {}

                            /**
                             * 其他房间用户发布的音频资源静音或者取消静音
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             * @param rcrtcInputStream 音频流
                             * @param mute true表示静音,false表示取消静音
                             */
                            @Override
                            public void onRemoteUserMuteAudio(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean mute) {}

                            /**
                             * 远端用户打开或关闭发布的视频流。 例如用户开启或者关闭摄像头
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             * @param rcrtcInputStream 视频流
                             * @param mute true表示关闭,false表示打开
                             */
                            @Override
                            public void onRemoteUserMuteVideo(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean mute) {}

                            /**
                             * 房间内用户取消发布资源
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             * @param list 远端用户取消发布的资源
                             */
                            @Override
                            public void onRemoteUserUnpublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {}

                            /**
                             * 用户加入房间
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             */
                            @Override
                            public void onUserJoined(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

                            /**
                             * 用户离开房间
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             */
                            @Override
                            public void onUserLeft(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

                            /**
                             * 用户离线
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param rcrtcRemoteUser 远端用户
                             */
                            @Override
                            public void onUserOffline(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

                            /**
                             * 自己退出其他房间。 例如断网退出等
                             *
                             * @param rcrtcOtherRoom 加入的其他房间对象
                             * @param reasonCode 状态码
                             */
                            @Override
                            public void onLeaveRoom(RCRTCOtherRoom rcrtcOtherRoom, int reasonCode) {}
                        });
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

# 离开副房间

输入参数说明

参数 类型 说明
roomId String 需要离开的其他房间号码
notifyFinished boolean 离开副房间时是否结束连麦。如果为true,本端将会退出该副房间。连麦中的其他用户将收到回调通知
callBack IRCRTCResultCallback 发送回调

回调参数说明

onFailed 说明:

回调参数 回调类型 说明
errorCode RTCErrorCode (opens new window) 音视频状态码

代码示例

RCRTCEngine.getInstance().leaveOtherRoom(roomId, notifyFinished, new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
        
    }

    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {
    
    }
});
已复制
1
2
3
4
5
6
7
8
9
10
11

# 邀请连麦流程

场景一

邀请方发起邀请后,邀请方又取消邀请。

此场景中被邀请方未做任何操作,仅被动收到两次代理回调。

邀请方 被邀请方
步骤1:调用 RCRTCLocalUser (opens new window) 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请 步骤2:在 IRCRTCRoomEventsListener (opens new window) 中收到 onRequestJoinOtherRoom 邀请回调
步骤3:调用 RCRTCLocalUser 类中的 cancelRequestJoinOtherRoom 方法结束之前发起的邀请 步骤4:在 IRCRTCRoomEventsListener (opens new window) 中收到 onCancelRequestOtherRoom 取消受邀请的回调

场景二

邀请方发起邀请后,被邀请方应答同意。

此场景中被邀请方应答同意,只有被邀请方不会收到应答的回调,包含邀请人在内两个房间的所有非观众用户都会收到代理回调。

邀请方 被邀请方
步骤1:调用 RCRTCLocalUser (opens new window) 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请 步骤2:在 IRCRTCRoomEventsListener (opens new window) 中收到 onRequestJoinOtherRoom 邀请回调
步骤4:包含邀请人在内两个房间的所有非观众用户,不包含被邀请方,会在 IRCRTCRoomEventsListener (opens new window) 中收到 onResponseJoinOtherRoom 应答回调 步骤3:调用 RCRTCLocalUser (opens new window) 类中的 responseJoinOtherRoom 应答邀请,其中,agree 参数的值为 true

场景三

邀请方发起邀请后,被邀请方应答拒绝。

此场景中被邀请方应答拒绝,只有邀请方会收到应答拒绝的回调,其他所有用户都不会收到代理回调。

邀请方 被邀请方
步骤1:调用 RCRTCLocalUser (opens new window) 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请 步骤2:在 IRCRTCRoomEventsListener (opens new window) 中收到 onRequestJoinOtherRoom 邀请回调
步骤4:只有邀请方会收到应答拒绝的回调,其他所有用户都不会收到 IRCRTCRoomEventsListener (opens new window) 中的 onResponseJoinOtherRoom 应答回调 步骤3:调用 RCRTCLocalUser (opens new window) 类中的 responseJoinOtherRoom 应答邀请,其中,agree 参数的值为 false

# 加入副房间流程

场景四

场景二 的前提下,

邀请方在收到应答同意的回调后,加入被邀请方的房间,即:邀请方加入的副房间。

被邀请方在调用应答同意后,加入邀请方的房间,即:被邀请方加入的副房间。

邀请方 被邀请方
步骤2:在收到被邀请方同意代理回调后,调用 RCRTCEngine (opens new window)joinOtherRoom 方法加入副房间 步骤1:在应答邀请同意后,调用 RCRTCEngine (opens new window)joinOtherRoom 方法加入副房间

场景五

在加入主房间前,如果主房间的某用户已经与其他房间另一用户成功建立跨房间连麦。

可以通过加入主房间成功后得到的 RCRTCRoom (opens new window) 对象中检查 getOtherRoomIds() 中是否存在房间中的用户已经加入的副房间。如果存在,可选择是否加入其他副房间

/**
* 主房间中主播已经加入的副房间Id列表
*/
List<String> getOtherRoomIds();
已复制
1
2
3
4
跨房间连麦成功后加入主房间的用户
步骤1:调用 RCRTCEngine (opens new window)joinRoom 方法加入主房间
步骤2:检查发现 getOtherRoomIds() 中存在其他副房间
步骤3:调用 RCRTCEnginejoinOtherRoom 方法加入副房间

# 订阅流程

场景四场景五 的前提下,

场景六

RCRTCEngine.getInstance().joinOtherRoom(roomId, new IRCRTCResultDataCallback<RCRTCOtherRoom>() {
            @Override
            public void onSuccess(RCRTCOtherRoom rcrtcOtherRoom) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        List<RCRTCInputStream> inputStreamList=new ArrayList<>();
                        //遍历远端用户列表
                        for (int i = 0; i < rcrtcOtherRoom.getRemoteUsers().size(); i++) {
                            //遍历远端用户发布的资源列表
                            for (RCRTCInputStream stream : rcrtcOtherRoom.getRemoteUsers().get(i).getStreams()) {
                                if(stream.getMediaType()== RCRTCMediaType.VIDEO){
                                    //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示
                                    RCRTCVideoView remoteView = new RCRTCVideoView(MainActivity.this);
                                    ((RCRTCVideoInputStream)stream).setVideoView(remoteView);
                                    //todo 本demo只演示添加1个远端用户的视图
                                    frameyout_remote.removeAllViews();
                                    frameyout_remote.addView(remoteView);
                                }
                                //如果要订阅所有远端用户的流。将其保存,方便后面统一订阅
                                inputStreamList.add(stream);
                            }
                        }
                        //开始订阅资源
                        RCRTCRoom.getLocalUser().subscribeStreams(inputStreamList, new IRCRTCResultCallback() {
                            @Override
                            public void onSuccess() {
                               
                            }

                            @Override
                            public void onFailed(RTCErrorCode rtcErrorCode) {
                               
                            }
                        });
                    }
                });
            }

            @Override
            public void onFailed(RTCErrorCode rtcErrorCode) {
               
            }
        });
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Override
public void onRemoteUserPublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            //遍历远端用户发布的资源列表
            for (RCRTCInputStream stream : list) {
                if(stream.getMediaType()== RCRTCMediaType.VIDEO){
                    //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示
                    RCRTCVideoView remoteView = new RCRTCVideoView(MainActivity.this);
                    ((RCRTCVideoInputStream)stream).setVideoView(remoteView);
                    frameyout_remote.removeAllViews();
                    frameyout_remote.addView(remoteView);
                }
            }
            //开始订阅资源
            RCRTCRoom.getLocalUser().subscribeStreams(list, new IRCRTCResultCallback() {
                @Override
                public void onSuccess() {
                    
                }

                @Override
                public void onFailed(RTCErrorCode rtcErrorCode) {
                    
                }
            });
        }
    });
}
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 离开副房间流程

场景七

已经加入副房间的用户,需要退出副房间时,可以调用 RCRTCEngine (opens new window) 中的 leaveOtherRoom(String roomId, boolean notifyFinished, IRCRTCResultCallback callBack) 方法。

此方法内部会取消订阅已经订阅的副房间所有用户音视频资源,上层无需自行取消订阅。

@Override
public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
}
已复制
1
2
3
    /**
     * 用户离开房间
     *
     * @param rcrtcBaseRoom 加入的其他房间对象
     * @param rcrtcRemoteUser 远端用户
     */
@Override
public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
}
已复制
1
2
3
4
5
6
7
8
9
    /**
     * 收到结束跨房间连麦的通知
     *
     * @param roomId 结束连麦的房间 Id
     * @param userId 发起结束连麦的用户 id
     */
@Override
public void onFinishOtherRoom(String roomId, String userId) {
    super.onFinishOtherRoom(roomId, userId);
}
已复制
1
2
3
4
5
6
7
8
9
10

# 被服务端踢出房间流程

通过调用服务端 API 可以将指定房间的指定用户踢出该房间。

  • 在踢出某个用户之前 ,建议先通过服务下发消息让此客户端执行结束跨房间连麦 ,然后再从主房间踢出违禁用户。
  • 被踢出的房间是该用户加入的主房间时,RongRTCLib 内部会调用 RCRTCEngine.getInstance().leaveRoom 方法先退出已经加入的副房间,再退出主房间并销毁资源。UI 层无需再次调用离开主、副房间的方法,只处理上层逻辑即可。
  • 被踢出的房间是该用户加入的副房间时,RongRTCLib 内部会调用 IRCRTCOtherRoomEventsListener (opens new window)onKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) 方法仅退出指定的副房间,并取消订阅已经订阅的该副房间中用户的音视频资源,UI 层无需再次调用离开副房间的方法,只处理上层逻辑即可。
/**
 * 被服务端踢下线
 * <p>如果用户在房间内, 此时收到服务器封禁的通知, SDK 会关闭音视频连接, 释放资源,
 * 将用户踢出房间, 回调通知用户</p>
 *
 * @param rcrtcBaseRoom 加入的其他房间对象
 */
@Override
public void onKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) {
    super.onKickedByServer(rcrtcBaseRoom);
}
已复制
1
2
3
4
5
6
7
8
9
10
11

文档是否解决您的问题 ?

如果遇到产品相关问题,您可 提交工单 寻求帮助