human: 如何处理七牛云的实时音视频跨房媒体转发

gpt: [实时音视频](https://developer.qiniu.com/rtc) > 使用指南 > Android >跨房媒体转发

#  跨房媒体转发

最近更新时间: 2022-11-24 18:43:48

本文主要介绍跨房媒体转发的使用以及场景

跨房媒体转发允许主播不离开自己的所在的房间，仅通过信令的操作，转发自己的音视频到其他的房间。七牛 RTC SDK
支持同时转发多路至多个房间（具体按照设备状况以及网络状况决定）。依赖此功能，可以很方便的实现直播过程中的连麦，小班课等业务。

# 名词解释

场景：

  * [QNClientMode.LIVE](https://developer.qiniu.com/rtc/10162/QNClientMode#LIVE): 用于互动直播场景，可以通过设置角色来控制权限。主播可以发布和订阅音视频，观众仅能订阅音视频。
  * [QNClientMode.RTC](https://developer.qiniu.com/rtc/10162/QNClientMode#RTC): 用于通信场景，所有人都可以发布自己的音视频，不可设置角色。

角色：

  * [QNClientRole.BROADCASTER](https://developer.qiniu.com/rtc/10163/QNClientRole#BROADCASTER): 主播角色，拥有发布和订阅音视频的权限。
  * [QNClientRole.AUDIENCE](https://developer.qiniu.com/rtc/10163/QNClientRole#AUDIENCE): 观众角色，仅有订阅音视频的权限。

# 使用前注意事项

**请注意当前跨房功能仅对场景为直播，且角色为主播的场景下才能使用：**

    
    
    // 使用直播场景和主播角色来创建 QNRTCClient
    QNRTCClientConfig clientConfig = new QNRTCClientConfig(QNClientMode.LIVE, QNClientRole.BROADCASTER);
    QNRTCClient client = QNRTC.createClient(clientConfig, this);
    
    // 创建 client 后依然可以修改角色，但是无法修改场景
    client.setClientRole(QNClientRole.BROADCASTER, QNClientRoleResultCallback);
    

对于以下几种情况：

  * 场景为 [QNClientMode.RTC](https://developer.qiniu.com/rtc/10162/QNClientMode#RTC)，则必须使用 [QNClientMode.LIVE](https://developer.qiniu.com/rtc/10162/QNClientMode#LIVE) 重新创建房间。
  * 已加入房间，且场景为 [QNClientMode.LIVE](https://developer.qiniu.com/rtc/10162/QNClientMode#LIVE) ，但是角色为 [QNClientRole.AUDIENCE](https://developer.qiniu.com/rtc/10163/QNClientRole#AUDIENCE)，则不需要退出房间，执行以下步骤即可： 
    1. 调用 `client.setClientRole(QNClientRole.BROADCASTER, QNClientRoleResultCallback)`；
    2. 等待 `QNClientRoleResultCallback.onResult(QNClientRole newRole)` 触发，且角色成功切换为 `QNClientRole.BROADCASTER`。
    3. 调用跨房媒体转发 API。

# 开启跨房媒体转发

通过
[QNRTCClient.startMediaRelay](https://developer.qiniu.com/rtc/8684/QNRTCClient#startMediaRelay)
接口开启跨房媒体转发，在 `QNMediaRelayResultCallback.onResult` 中收到回调，具体回调状态参考
`QNMediaRelayState`，成功会返回 `Success`，否则返回其他值:
`UNKNOWN`，`INVALID_TOKEN`，`NO_ROOM`，`ROOM_CLOSED`，`PLAYER_EXISTED`。

    
    
    public void startMediaRelay(QNMediaRelayConfiguration configuration, QNMediaRelayResultCallback callback);
    

其中，[QNMediaRelayConfiguration](https://developer.qiniu.com/rtc/10165/QNMediaRelayConfiguration)
为跨房媒体转发的配置类，主要包含如下配置方法：

    
    
    QNMediaRelayConfiguration.setSrcRoomInfo(QNMediaRelayInfo srcRoomInfo);  // 设置源房间信息
    QNMediaRelayConfiguration.addDestRoomInfo(QNMediaRelayInfo destRoomInfo); // 添加目标房间信息
    

[QNMediaRelayResultCallback](https://developer.qiniu.com/rtc/10167/QNMediaRelayResultCallback)
为跨房媒体转发操作的结果监听，主要包含如下回调接口：

    
    
    public interface QNMediaRelayResultCallback {
        /**
         * 跨房媒体转发操作成功时触发
         * 跨房媒体转发结果以回调的房间名相对应的 QNMediaRelayState 为准，包括 SUCCESS、INVALID_TOKEN、NO_ROOM 等
         *
         * @param stateMap 具体目标房间状态， key 为房间名， value 为状态
         */
        void onResult(Map<String, QNMediaRelayState> stateMap);
    
        /**
         * 失败回调
         *
         * @param errorCode 失败 error code
         * @param description 失败描述
         */
        void onError(int errorCode, String description);
    }
    

示例代码如下：

    
    
    QNMediaRelayInfo sourceInfo = new QNMediaRelayInfo(roomName, token);
    QNMediaRelayConfiguration configuration = new QNMediaRelayConfiguration(sourceInfo);
    // 添加目标房间
    QNMediaRelayInfo destInfo1 = new QNMediaRelayInfo(destRoomName1, destRoomRelayToken1);
    QNMediaRelayInfo destInfo2 = new QNMediaRelayInfo(destRoomName2, destRoomRelayToken2);
    configuration.addDestRoomInfo(destInfo1);
    configuration.addDestRoomInfo(destInfo2);
    engine.startMediaRelay(configuration, new QNMediaRelayResultCallback());
    

# 更新跨房媒体转发

通过
[QNRTCClient.updateMediaRelay](https://developer.qiniu.com/rtc/8684/QNRTCClient#updateMediaRelay)
接口更新跨房媒体转发，在 `QNMediaRelayResultCallback.onResult` 中收到回调
**注意此接口中的`configuration` 为全量更新，如已经开启的跨房的目标房间未被包含，则会被停止**

    
    
    public void updateMediaRelay(QNMediaRelayConfiguration configuration, QNMediaRelayResultCallback callback);
    

例：

    
    
    QNMediaRelayInfo sourceInfo = new QNMediaRelayInfo(roomName, token);
    QNMediaRelayConfiguration configuration = new QNMediaRelayConfiguration(sourceInfo);
    // 添加目标房间
    QNMediaRelayInfo destInfo1 = new QNMediaRelayInfo(destRoomName1, destRoomRelayToken1);
    QNMediaRelayInfo destInfo2 = new QNMediaRelayInfo(destRoomName2, destRoomRelayToken2);
    configuration.addDestRoomInfo(destInfo1);
    configuration.addDestRoomInfo(destInfo2);
    engine.updateMediaRelay(configuration, new QNMediaRelayResultCallback());
    

# 停止跨房媒体转发

通过
[QNRTCClient.stopMediaRelay](https://developer.qiniu.com/rtc/8684/QNRTCClient#stopMediaRelay)
接口停止跨房媒体转发，所有已开启的跨房行为将被停止，在 `QNMediaRelayResultCallback.onResult` 中收到回调

    
    
    public void stopMediaRelay(QNMediaRelayResultCallback callback);
    

# 事件通知

  * 主动跨房的主播 A，在转发过程中可通过 [QNClientEventListener.onMediaRelayStateChanged](https://developer.qiniu.com/rtc/8643/QNClientEventListener#onMediaRelayStateChanged) 回调接收当前跨房媒体转发流的状态更新；注意，该回调非主动调用触发。
  * 被跨房的主播 B，当主播 A 跨房成功之后，会触发 [QNClientEventListener.onUserJoined](https://developer.qiniu.com/rtc/8643/QNClientEventListener#onUserJoined) 等用户加入，离开，发布音视频等回调。

# 直播连麦 pk

使用跨房媒体转发方案，可以很方便的解决连麦 pk 这类场景的需求。 主播 A 不再需要离开自己的房间，只需通过以下步骤即可：

  1. 业务协商，主播 A 通过 `RTCSDK` 自定义消息或者业务服务器长连接向主播 B 发送连麦请求，如果请求通过，则进行下一步
  2. 主播 A 调用 `QNRTCClient.startMediaRelay`，主播 B 收到主播 A 加入房间和发布音视频等一系列消息后，再使用 `setTranscodingLiveStreamingTracks` 方法更新合流布局即可。[CDN 转推参考](https://developer.qiniu.com/rtc/development_guidelines/8770/turn-the-cdn-push-android)。
  3. 主播 B 操作同主播 A。
  4. 连麦结束后，各自调用 `QNRTCClient.stopMediaRelay` 停止跨房，并调用 `removeTranscodingLiveStreamingTracks` 移除连麦布局。[CDN 转推参考](https://developer.qiniu.com/rtc/development_guidelines/8770/turn-the-cdn-push-android)。
  5. 结束

# 示例代码

跨房媒体转发场景的示例代码可参考 [QNRTC-API-Examples](https://github.com/pili-
engineering/QNRTC-Android/blob/master/QNRTC-API-
Examples/app/src/main/java/com/qiniu/droid/rtc/api/examples/activity/MediaRelayActivity.java)。

以上内容是否对您有帮助？