human: 如何处理七牛云的实时音视频CDN 转推

gpt: [实时音视频](https://developer.qiniu.com/rtc) > 使用指南 > Android >CDN 转推

#  CDN 转推

最近更新时间: 2023-08-17 15:52:41

本文主要介绍 CDN 转推的使用姿势及其应用场景。

CDN 转推可实现直播场景的功能，实时音视频场景下的直播主要包括三个部分：**单路流直播** 、**多路流合流直播** 以及**两者结合可切换的直播场景**
。

> CDN 转推需要配置本地或者远端的音视频 Track，因此，**调用转推接口前请务必保证加入了房间，并且已经发布或者订阅了相应的音视频 Track**

下面将会就三种场景的使用姿势进行说明。

# 设置监听

在进行 CDN 转推之前，需要设置 CDN 转推流的状态监听：

    
    
    mClient.setLiveStreamingListener(new QNLiveStreamingListener() {
        @Override
        public void onStarted(String streamID) {
            // 转推任务创建成功时触发此回调
        }
    
        @Override
        public void onStopped(String streamID) {
            // 转推任务成功停止时触发此回调
        }
    
        @Override
        public void onTranscodingTracksUpdated(String streamID) {
            // 合流布局更新成功时触发此回调
        }
    
        @Override
        public void onError(String streamID, QNLiveStreamingErrorInfo errorInfo) {
            // 转推任务出错时触发此回调
        }
    });
    

其中，转推任务出错时的错误原因可参考
[QNLiveStreamingErrorInfo](https://developer.qiniu.com/rtc/api/8657/QNLiveStreamingErrorInfo)。对应的错误码可参考
[CDN 转推相关错误码](https://developer.qiniu.com/rtc/development_guidelines/9904/rtc-
error-code-android#5)

在设置好监听后，便可以基于业务场景进行`单路转推任务`或者`合流转推任务`的创建了。

# 单路流直播

单路流直播的场景，顾名思义，就是将一条音视频流直接转推到直播服务器，主要适用于`不包含连麦的秀场直播`、`连麦中需要将某一路流单独转推落存储`等场景。

场景示意图如下：

![单路流直播](http://docs.qnsdk.com/forward_job.jpg)

注意：如果主播有两路视频流（采集+录屏）需要合流转推，请参考多路流合流直播场景实现

单路流转推场景主要实现步骤如下：

## 创建单路转推任务

[QNDirectLiveStreamingConfig](https://developer.qiniu.com/rtc/api/8651/QNDirectLiveStreamingConfig)
用于配置单路转推的相关信息，包括推流地址、参与 CDN 转推的音视频轨等。

创建转推任务的示例代码如下：

    
    
    // 创建单路转推任务配置对象
    QNDirectLiveStreamingConfig mDirectLiveStreamingConfig = new QNDirectLiveStreamingConfig();
    // 设置 stream id，该 id 为转推任务的唯一标识符
    mDirectLiveStreamingConfig.setStreamID(mRoomName);
    // 设置推流地址
    mDirectLiveStreamingConfig.setUrl("publish url");
    // 设置单路流中的音频轨，仅支持一路音频的设置，重复设置会被覆盖
    mDirectLiveStreamingConfig.setAudioTrack(mMicrophoneAudioTrack);
    // 设置单路流中的视频轨，仅支持一路视频的设置，重复设置会被覆盖
    mDirectLiveStreamingConfig.setVideoTrack(mCameraVideoTrack);
    // 开始进行单路转推
    mClient.startLiveStreaming(mDirectLiveStreamingConfig);
    

单路转推任务创建成功后，会触发上述 `QNLiveStreamingListener.onStarted`
回调接口，回调该接口即代表成功开启了单路流转推，可以通过相应的播放链接拉取直播流进行观看。

**注意：**

  1. **QNDirectLiveStreamingConfig 仅支持配置一路视频轨和一路音频轨，重复设置会被覆盖**
  2. **配置单路转推任务时，请务必保证待转推的音视频 Track 均已成功发布**
  3. **单路转推场景下，需确保在创建视频 Track 时通过[QNVideoEncoderConfig](https://developer.qiniu.com/rtc/api/8701/QNVideoEncoderConfig#QNVideoEncoderConfig%5B2/2%5D) 将视频降级模式 [QNDegradationPreference](https://developer.qiniu.com/rtc/8770/turn-the-cdn-push-android/12393/QNDegradationPreference) 设置为 `QNDegradationPreference.MAINTAIN_RESOLUTION` 或者 `QNDegradationPreference.ADAPT_BITRATE_ONLY`，保证推流分辨率不会改变，否则可能会出现不可预期的问题！！！**

## 停止单路转推任务

可以通过如下方式停止单路转推任务：

    
    
    mClient.stopLiveStreaming(mDirectLiveStreamingConfig);
    

单路转推任务停止成功后，会触发上述 `QNLiveStreamingListener.onStopped` 回调接口。

######

# 多路流合流直播

多路流合流直播场景，主要适用于`连麦互动直播`、`PK
直播`以及`单主播需要两路以上视频合流转推`等场景。简单来说，就是对连麦各方的视频画面进行合流，然后转推。这种场景相较于纯直播场景的单路流转推会复杂一些。

场景示意图如下：

![多路流合流直播](http://docs.qnsdk.com/merge_job.jpg)

为了实现该场景，首先，需要了解下相关配置类及其作用：

  * [QNTranscodingLiveStreamingConfig:](https://developer.qiniu.com/rtc/api/8696/QNTranscodingLiveStreamingConfig) 用于配置合流的基本参数，包括任务 id、推流地址、合流的宽高、码率等信息。
  * [QNTranscodingLiveStreamingTrack:](https://developer.qiniu.com/rtc/api/8698/QNTranscodingLiveStreamingTrack) 用于配置参与 CDN 合流的每一路媒体 Track 在合流画布中的位置、大小等信息。

了解上述概念后，该场景的主要实现步骤如下：

## 开启合流直播

### 创建 QNTranscodingLiveStreamingConfig

    
    
    QNTranscodingLiveStreamingConfig mTranscodingLiveStreamingConfig = new QNTranscodingLiveStreamingConfig();
    mTranscodingLiveStreamingConfig.setStreamID(streamID); // 设置 stream id，该 id 为合流任务的唯一标识符
    mTranscodingLiveStreamingConfig.setUrl("publish url"); // 设置合流任务的推流地址
    mTranscodingLiveStreamingConfig.setWidth(480); // 设置合流画布的宽度
    mTranscodingLiveStreamingConfig.setHeight(848); // 设置合流画布的高度
    mTranscodingLiveStreamingConfig.setVideoFrameRate(20); // 设置合流任务的视频帧率
    mTranscodingLiveStreamingConfig.setRenderMode(QNRenderMode.ASPECT_FILL); // 设置合流任务的默认画面填充方式
    mTranscodingLiveStreamingConfig.setBitrate(1000); // 设置合流任务的码率，单位: kbps
    mTranscodingLiveStreamingConfig.setBackground(mBackgroundImage); // 设置合流画布的背景图片，仅支持 HTTP
    mTranscodingLiveStreamingConfig.setWatermarks(Collections.singletonList(mWatermark)); // 设置合流任务的水印
    mClient.startLiveStreaming(mTranscodingLiveStreamingConfig); // 开始转推
    

合流任务创建成功后，会触发上述 `QNLiveStreamingListener.onStarted` 回调接口。可以在该回调接口中设置合流布局

### 设置合流布局

合流任务创建成功之后，即可基于已发布的
[Track](https://developer.qiniu.com/rtc/quick_start/9909/the-rtc-basic-
concept#track) 进行相应的合流布局配置。配置布局前，需要先了解
[QNTranscodingLiveStreamingTrack](https://developer.qiniu.com/rtc/api/8698/QNTranscodingLiveStreamingTrack)
的概念。布局配置的示例代码如下：

    
    
    // 配置待合流转推的视频 Track
    QNTranscodingLiveStreamingTrack videoTranscodingTrack = new QNTranscodingLiveStreamingTrack();
    videoTranscodingTrack.setTrackID(videoTrackID); // 设置待合流 Track id
    videoTranscodingTrack.setX(x); // 设置 Track 画面在合流画面中位置的 x 轴坐标
    videoTranscodingTrack.setY(y); // 设置 Track 画面在合流画面中位置的 y 轴坐标
    videoTranscodingTrack.setZOrder(zOrder); // 设置 Track 画面在合流画面中的 zOrder 层级，zOrder 值越大，画面层级越高
    videoTranscodingTrack.setWidth(width); // 设置 Track 画面在合流画面中位置宽度
    videoTranscodingTrack.setHeight(height); // 设置 Track 画面在合流画面中位置高度
    
    // 配置待合流转推的音频 Track
    QNTranscodingLiveStreamingTrack audioTranscodingTrack = new QNTranscodingLiveStreamingTrack();
    audioTranscodingTrack.setTrackID(audioTrackID); // 设置待合流 Track id
    

其中，远端用户的 trackID 可以通过 SDK 提供的相关回调返回的
[QNRemoteAudioTrack](https://developer.qiniu.com/rtc/api/8674/QNRemoteAudioTrack)
和
[QNRemoteVideoTrack](https://developer.qiniu.com/rtc/api/8680/QNRemoteVideoTrack)
获取：

    
    
    public interface QNClientEventListener {
        // 当成功订阅远端 Track 时会触发此回调
        void onSubscribed(String remoteUserID, List<QNRemoteAudioTrack> remoteAudioTracks, List<QNRemoteVideoTrack> remoteVideoTracks);
    }
    

通过上述代码创建或者更新已有的
[QNTranscodingLiveStreamingTrack](https://developer.qiniu.com/rtc/api/8698/QNTranscodingLiveStreamingTrack)
布局配置后，即可调用如下方法使得相应的布局配置生效：

    
    
    /**
     * 新增、更新合流布局
     *
     * @param streamID 合流任务 id
     * @param transcodingTracks 待配置布局的 QNTranscodingLiveStreamingTrack 的列表
     */
    mClient.setTranscodingLiveStreamingTracks(String streamID, List<QNTranscodingLiveStreamingTrack> transcodingTracks);
    

当期望取消某路合流布局时，可以通过如下调用实现：

    
    
    /**
     * 设置取消合流布局
     *
     * @param streamID 合流任务 id
     * @param transcodingTracks 待移除布局的 QNTranscodingLiveStreamingTrack 的列表
     */
    mClient.removeTranscodingLiveStreamingTracks(String streamID, List<QNTranscodingLiveStreamingTrack> transcodingTracks);
    

**注意：配置合流转推任务时，请务必保证待转推的音视频 Track 均已成功发布**

## 停止合流直播

可以通过如下方式停止合流转推任务：

    
    
    mClient.stopLiveStreaming(mTranscodingLiveStreamingConfig);
    

合流转推任务停止成功后，会触发上述 `QNLiveStreamingListener.onStopped` 回调接口。

# 单路、多路切换直播

单路流、多路流合流二者切换的场景，主要适用于`有连麦需求的秀场直播`等场景，能够满足主播在自己单路流直播和连麦两路流合流直播二者间切换的需求。对于该场景的实现，需要注意的问题是，在两种场景切换的过程中，如何保证观看端不会断流黑屏。

为了避免切换过程中断流黑屏的问题，这里我们引入 `serialnum` 的概念以实现两路流的平滑切换：

  * [QNDirectLiveStreamingConfig](https://developer.qiniu.com/rtc/api/8651/QNDirectLiveStreamingConfig) 和 [QNTranscodingLiveStreamingConfig](https://developer.qiniu.com/rtc/api/8696/QNTranscodingLiveStreamingConfig) 两种任务场景推流地址需要保持一致以避免播放端需要实现多余的切流操作
  * 由于上述完全一致的地址可能会导致抢流的现象出现，所以需要在推流地址后面加上 `serialnum` 的参数，如 "rtmp://domain/app/streamName?serialnum=xxx"，其中，serialnum 决定流的优先级，从 1 开始递增，值越大，优先级越高，优先级低的流会被停止掉，便可避免出现抢流的现象。也基于此，合流任务必须使用自定义合流任务，以便自定义推流地址。

综上，单路流、合流切换场景的实现步骤如下：

  1. 创建单路流转推任务，同时进行单路流直播
  2. 需要从单路转推任务切换到合流转推任务时，`创建自定义合流任务`，注意要使用自定义合流任务指定带有 `serialnum` 参数的推流地址，在收到合流转推任务的 `onStarted` 回调之后，在回调中执行 `mClient.stopLiveStreaming(mDirectLiveStreamingConfig)` 来停止单路转推任务
  3. 需要从合流转推任务切换到单路转推任务时，创建单路转推任务，其推流地址需要带有 `serialnum` 参数，在收到单路转推任务的 `onStarted` 回调之后，在回调中执行 `mClient.stopLiveStreaming(mTranscodingLiveStreamingConfig)` 来停止合流转推任务

通过上述方式，即可实现单路流直播、多路流合流直播之间的切换，具体实现也可参照 [demo](https://github.com/pili-
engineering/QNRTCLive-
Android/blob/master/QNDroidRTCLiveDemo/app/src/main/java/com/qiniu/droid/rtc/live/demo/activity/LiveRoomActivity.java)
中的相关实现

######

# 发送 SEI

CDN 转推场景支持 SEI 信息的发送，设置方式如下：

    
    
    String seiMsg = "SEI message";
    // Camera 视频 Track 发送 SEI
    mCameraVideoTrack.sendSEI(seiMsg.getBytes(StandardCharsets.UTF_8), 1);
    // 屏幕录制视频 Track 发送 SEI
    mScreenVideoTrack.sendSEI(seiMsg.getBytes(StandardCharsets.UTF_8), 1);
    // 自定义视频 Track 发送 SEI
    mCustomVideoTrack.sendSEI(seiMsg.getBytes(StandardCharsets.UTF_8), 1);
    

>   1. **对于单路流直播的场景** ，调用上述接口后，播放端即可通过使用支持 SEI 解析的播放器获取到对应的 SEI 信息。
>   2. **对于多路流合流直播的场景** ，调用上述接口后，还需在配置合流布局时，通过
> [QNTranscodingLiveStreamingTrack.setSEIEnabled](https://developer.qiniu.com/rtc/api/8698/QNTranscodingLiveStreamingTrack#setSEIEnabled)
> 接口**指定允许携带 SEI 信息的视频 Track** ，才可正常推送 SEI 信息。需要注意的是，一个合流任务中，仅支持一路视频 Track 携带
> SEI 信息。
>

# 注意事项

  * CDN 转推需要配置本地或者远端的音视频 Track，因此，**调用转推接口前请务必保证加入了房间，并且已经发布或者订阅了相应的音视频 Track**
  * **单路流直播场景，一路流仅支持一路音频轨和一路视频轨的设置，重复设置会被覆盖**
  * **为保证单路流直播的质量，需确保在创建视频 Track 时通过[QNVideoEncoderConfig](https://developer.qiniu.com/rtc/api/8701/QNVideoEncoderConfig#QNVideoEncoderConfig%5B2/2%5D) 将视频降级模式 [QNDegradationPreference](https://developer.qiniu.com/rtc/8770/turn-the-cdn-push-android/12393/QNDegradationPreference) 设置为 `QNDegradationPreference.MAINTAIN_RESOLUTION` 或者 `QNDegradationPreference.ADAPT_BITRATE_ONLY`，保证推流分辨率不会改变**
  * **如果场景涉及到单路流直播、多路流合流直播之间的切换，那么合流任务务必使用自定义合流任务以指定带有`serialnum` 的推流地址。其中，serialnum 决定流的优先级，从 1 开始递增，值越大，优先级越高**

# 示例代码

CDN 转推场景的示例代码可参考 [QNRTC-API-Examples](https://github.com/pili-
engineering/QNRTC-Android/tree/master/QNRTC-API-Examples)。

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