跳到主要内容

跨房间连麦

跨房间连麦需要区分“主房间”和“副房间”的概念,主副房间是相对概念,定义如下:

  • 主房间:本端最先加入的房间,即 RCRTCRoom
  • 副房间:在连麦邀请被接受后,双方加入对方房间,对方房间即:RCRTCOtherRoom

开始跨房间连麦前,双方都需要先加入各自的主房间;未加入主房间前,无法发起或接收跨房间连麦邀请。

两种房间类型对应不同的事件回调:主房间使用 IRCRTCRoomEventsListener,副房间使用 IRCRTCOtherRoomEventsListener

主流程

(height=800)

发起邀请

向指定用户发送跨房间连麦请求:在加入房间成功的回调中,通过 RCRTCRoom 获取 RCRTCLocalUser 对象,调用 requestJoinOtherRoom 方法。

示例代码:

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

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

取消邀请

收到其他房间主播的跨房间连麦邀请后,如果不打算加入,调用 RCRTCLocalUsercancelRequestJoinOtherRoom 取消进行中的邀请。

示例代码

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

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

应答邀请

收到跨房间连麦邀请后,如果同意加入,需要先调用 RCRTCLocalUserresponseJoinOtherRoom 应答,再调用 joinOtherRoom 加入副房间。

示例代码

Java
/**
* <p>
* 1. 当 inviteeAutoMix 为 true 时:
*
* 1.1 如果邀请方在发送连麦请求之前发布了资源,当被邀请方加入邀请方房间成功后,服务器会把邀请方的流资源合并到被邀请方视图(默认仅悬浮布局合流)上。
*
* 1.2 如果邀请方在发送连麦请求之前未发布资源,将在邀请方发布资源成功后,服务器才会把邀请方的资源合并到被邀请方视图(默认仅悬浮布局合流)上。
*
* 2. 无论 inviteeAutoMix 为 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) {
}
});

加入副房间

可调用 joinOtherRoom 方法,加入副房间。

示例代码

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

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

注册其他房间事件监听

  1. 在加入副房间成功后的回调中,获取 RCRTCOtherRoom 对象,调用 registerOtherRoomEventsListener 注册副房间事件监听。当副房间主播加入、离开、发布资源时会触发回调;在回调中按需订阅音视频资源。可进行音视频通话。
  2. 在不使用或退出房间前,调用 RCRTCOtherRoom.unregisterOtherRoomEventsListener 取消注册。
Java
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) {}
});

离开副房间

需要结束跨房间连麦时,调用 RCRTCEngineleaveOtherRoom 离开副房间。

示例代码:

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

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

邀请连麦流程

  • 场景一:邀请方发起邀请后又取消邀请。

    提示

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

    邀请方被邀请方
    步骤 1:调用 RCRTCLocalUserrequestJoinOtherRoom 发起跨房间连麦邀请步骤 2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
    步骤 3:调用 RCRTCLocalUsercancelRequestJoinOtherRoom 方法结束之前发起的邀请步骤 4:在 IRCRTCRoomEventsListener 中收到 onCancelRequestOtherRoom 取消受邀请的回调
  • 场景二:邀请方发起邀请后,被邀请方应答同意。

    提示

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

    邀请方被邀请方
    步骤 1:调用 RCRTCLocalUserrequestJoinOtherRoom 发起跨房间连麦邀请步骤 2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
    步骤 4:包含邀请人在内的两个房间中所有非观众用户(不含被邀请方)会在 IRCRTCRoomEventsListener 中收到 onResponseJoinOtherRoom 应答回调步骤 3:调用 RCRTCLocalUserresponseJoinOtherRoom 应答邀请,其中 agree 参数设为 true
  • 场景三:邀请方发起邀请后,被邀请方应答拒绝。

    提示

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

    邀请方被邀请方
    步骤 1:调用 RCRTCLocalUserrequestJoinOtherRoom 发起跨房间连麦邀请步骤 2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
    步骤 4:只有邀请方会收到应答拒绝回调;其他用户不会在 IRCRTCRoomEventsListener 中收到 onResponseJoinOtherRoom 应答回调步骤 3:调用 RCRTCLocalUserresponseJoinOtherRoom 应答邀请,其中 agree 参数设为 false

加入副房间流程

  • 场景四:基于“场景二”,邀请方在收到应答同意回调后加入被邀请方的房间(副房间);被邀请方在应答同意后加入邀请方的房间(副房间)。

    邀请方被邀请方
    步骤 2:在收到被邀请方同意回调后,调用 RCRTCEnginejoinOtherRoom 加入副房间步骤 1:在应答同意后,调用 RCRTCEnginejoinOtherRoom 加入副房间
  • 场景五:在加入主房间前,主房间的某用户已经与其他房间另一用户成功建立跨房间连麦。

    加入主房间成功后,可通过 RCRTCRoomgetOtherRoomIds() 检查是否存在房间中的用户已经加入的副房 间。如果存在,可选择是否加入其他副房间。

    Java
    /**
    * 主房间中主播已经加入的副房间 ID 列表
    */
    List<String> getOtherRoomIds();
    跨房间连麦成功后加入主房间的用户
    步骤 1:调用 RCRTCEnginejoinRoom 加入主房间
    步骤 2:检查发现 getOtherRoomIds() 中存在其他副房间
    步骤 3:调用 RCRTCEnginejoinOtherRoom 加入副房间

订阅流程

在“场景四”或“场景五”的前提下:

  • 场景六:方式一,订阅副房间用户已发布的音视频资源。加入副房间后,通过遍历取得副房间中所有远端用户中的 RCRTCInputStream 列表,再调用 RCRTCLocalUsersubscribeStreams 订阅副房间中远端用户已经发布的音视频资源。

    Java
    RCRTCEngine.getInstance().joinOtherRoom(roomId, new IRCRTCResultDataCallback<RCRTCOtherRoom>() {
    @Override
    public void onSuccess(RCRTCOtherRoom rcrtcOtherRoom) {
    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 示例仅演示添加 1 个远端用户的视图
    frameyout_remote.removeAllViews();
    frameyout_remote.addView(remoteView);
    }
    // 若要订阅所有远端用户的流,请将其保存,以便统一订阅
    inputStreamList.add(stream);
    }
    }
    // 开始订阅资源
    RCRTCRoom.getLocalUser().subscribeStreams(inputStreamList, new IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
    @Override
    public void onSuccess() {

    }
    @Override
    public void onSuccess(List<RCRTCInputStream> data) {

    }
    @Override
    // 如果 SDK ≥ 5.3.4,您可以使用 IRCRTCResultDataCallback,onFailed 方法会返回订阅失败的流列表和错误码。
    // 如果 SDK < 5.3.4,仅支持使用 IRCRTCResultCallback,onFailed 方法仅返回错误码。
    public void onFailed(List<RCRTCInputStream> failedStreams, RTCErrorCode errorCode) {

    }
    });
    }

    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {
    }
    });
  • 场景七:方式二,订阅副房间中“刚发布”的音视频资源。加入副房间后,当有副房间中远端用户发布资源时,会回调 IRCRTCOtherRoomEventsListeneronRemoteUserPublishResource 方法,调用 RCRTCLocalUsersubscribeStreams 订阅刚发布的资源。

    Java
    @Override
    public void onRemoteUserPublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {
    // 遍历远端用户发布的资源列表
    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 IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
    @Override
    public void onSuccess() {

    }
    @Override
    public void onSuccess(List<RCRTCInputStream> data) {
    }

    @Override
    // 如果 SDK ≥ 5.3.4,您可以使用 IRCRTCResultDataCallback,onFailed 方法会返回订阅失败的流列表和错误码。
    // 如果 SDK < 5.3.4,仅支持使用 IRCRTCResultCallback,onFailed 方法仅返回错误码。
    public void onFailed(List<RCRTCInputStream> failedStreams, RTCErrorCode errorCode) {

    }
    });
    }

离开副房间流程

  • 场景八:已加入副房间的用户需要退出副房间时,可调用 RCRTCEngineleaveOtherRoom(String roomId, boolean notifyFinished, IRCRTCResultCallback callBack) 方法。

    提示

    该方法会自动取消订阅已订阅的副房间所有用户的音视频资源,上层无需手动取消订阅。 当 notifyFinishedfalse 时,仅表示调用方离开副房间;其他用户会在 IRCRTCOtherRoomEventsListener 中收到 onUserLeft 回调。

Java
@Override
public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
}
  • notifyFinishedtrue 时,其他用户会在 IRCRTCOtherRoomEventsListener 中收到 onUserLeft,并在 IRCRTCRoomEventsListener 中收到 onFinishOtherRoom 回调。

    Java
    /**
    * 用户离开房间
    *
    * @param rcrtcBaseRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    */
    @Override
    public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
    }
    Java
    /**
    * 收到结束跨房间连麦的通知
    *
    * @param roomId 结束连麦的房间 ID
    * @param userId 发起结束连麦的用户 ID
    */
    @Override
    public void onFinishOtherRoom(String roomId, String userId) {
    super.onFinishOtherRoom(roomId, userId);
    }

被服务端踢出房间流程

提示

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

  • 在踢出某个用户之前,建议先通过服务下发消息让该客户端执行结束跨房间连麦,然后再从主房间踢出违禁用户。

  • 被踢出的房间是该用户加入的主房间时,RongRTCLib 内部会调用 RCRTCEngine.getInstance().leaveOtherRoom,先退出已加入的副房间,再退出主房间并销毁资源。UI 层无需再次调用离开主/副房间的方法,只需处理上层逻辑。

  • 被踢出的房间是该用户加入的副房间时,服务端操作离开房间,并取消订阅已订阅的该副房间内用户的音视频资源。在 IRCRTCOtherRoomEventsListeneronKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) 回调中返回房间相关信息,UI 层无需再次调用离开副房间的方法,只需处理上层逻辑。

Java
/**
* 被服务端踢下线
* <p>如果用户在房间内,收到服务器封禁通知时,SDK 会关闭音视频连接并释放资源,将用户踢出房间,并回调通知用户。</p>
*
* @param rcrtcBaseRoom 加入的其他房间对象
*/
@Override
public void onKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) {
super.onKickedByServer(rcrtcBaseRoom);
}