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

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

#  CDN 转推

最近更新时间: 2023-11-20 10:33:27

本部分介绍了 CDN 转推的使用姿势及其应用场景。

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

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

下面将会对这三种场景的使用姿势进行分别说明。

# 设置监听

在进行 CDN 转推之前，需要实现
[QNRTCClientDelegate](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate)
有关 CDN 转推的代理回调方法：

    
    
    - (void)RTCClient:(QNRTCClient *)client didStartLiveStreaming:(NSString *)streamID {
    	// 成功创建转推/合流转推任务的回调
    }
    
    - (void)RTCClient:(QNRTCClient *)client didStopLiveStreaming:(NSString *)streamID {
    	// 停止转推/合流转推任务的回调
    }
    
    - (void)RTCClient:(QNRTCClient *)client didTranscodingTracksUpdated:(NSString *)streamID {
    	// 更新合流布局的回调
    }
    
    - (void)RTCClient:(QNRTCClient *)client didErrorLiveStreaming:(NSString *)streamID errorInfo:(QNLiveStreamingErrorInfo *)errorInfo {
    	// 合流转推出错的回调
    }
    
    

其中，转推任务出错时的错误信息及原因可参考
[QNLiveStreamingErrorInfo](https://developer.qiniu.com/rtc/api/8864/QNLiveStreamingErrorInfo-
iOS)

在设置好
[QNRTCClientDelegate](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate)
代理并实现相应回调后，便可以基于实际业务场景进行[单路转推](https://developer.qiniu.com/rtc/quick_start/9909/the-
rtc-basic-
concept#direct_streaming)或者[合流转推](https://developer.qiniu.com/rtc/quick_start/9909/the-
rtc-basic-concept#transcoding_streaming)任务的创建和使用了。

# 单路流直播场景

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

场景示意图如下：

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

注意：如果主播有两路视频流（采集+录屏）需要合流转推，请参考[多路流合流直播场景](https://developer.qiniu.com/rtc/development_guidelines/9262/turn-
the-cdn-push-iOS#3)实现。

该场景的主要实现步骤如下：

## 创建单路转推任务

[QNDirectLiveStreamingConfig](https://developer.qiniu.com/rtc/api/8861/QNDirectLiveStreamingConfig-
iOS) 用于配置单路转推的相关信息，包括推流地址以及参与 CDN 转推的音视频
[Track](https://developer.qiniu.com/rtc/quick_start/9909/the-rtc-basic-
concept#track)。

相关配置及创建转推任务的示例代码如下：

    
    
    // 创建单路转推任务配置对象
    QNDirectLiveStreamingConfig *directLiveStreamingConfig = [[QNDirectLiveStreamingConfig alloc] init];
    // 设置 stream id，该 id 为合流任务的唯一标识符
    directLiveStreamingConfig.streamID = roomName;
    // 设置推流地址
    directLiveStreamingConfig.publishUrl = @"publish url";
    // 设置单路流中的音频轨，仅支持一路音频的设置，重复设置会被覆盖
    directLiveStreamingConfig.audioTrack = microphoneAudioTrack;
    // 设置单路流中的视频轨，仅支持一路视频的设置，重复设置会被覆盖
    directLiveStreamingConfig.videoTrack = cameraVideoTrack;
    // 开始进行单路转推
    [rtcClient startLiveStreamingWithDirect:directLiveStreamingConfig];
    

单路转推任务创建成功后，会触发
[QNRTCClientDelegate.didStartLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStartLiveStreaming)
回调接口：

    
    
    - (void)RTCClient:(QNRTCClient *)client didStartLiveStreaming:(NSString *)streamID;
    

创建成功后，就可以通过相应的播放链接拉取直播流进行观看了。

> 注意:
> [QNDirectLiveStreamingConfig](https://developer.qiniu.com/rtc/api/8861/QNDirectLiveStreamingConfig-
> iOS) 仅支持配置一路视频轨和一路音频轨，重复设置将会被覆盖。

## 停止单路转推任务

可以通过如下方式，调用
[QNRTCClient.stopLiveStreamingWithDirect](https://developer.qiniu.com/rtc/api/8836/QNRTCClient-
iOS#stopLiveStreamingWithDirect) 实现单路转推任务的停止：

    
    
    [rtcClient stopLiveStreamingWithDirect:directLiveStreamingConfig];
    

单路转推任务停止成功后，会触发
[QNRTCClientDelegate.didStopLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStopLiveStreaming)
回调：

    
    
    - (void)RTCClient:(QNRTCClient *)client didStopLiveStreaming:(NSString *)streamID;
    

停止转推成功后，相应的播放链接直播流就无法观看了。

# 多路流合流直播场景

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

场景示意图如下：

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

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

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

该场景的主要实现步骤如下：

## 开启合流直播

### 创建合流转推任务

    
    
    QNTranscodingLiveStreamingConfig *transcodingLiveStreamingConfig = [[QNTranscodingLiveStreamingConfig alloc] init];
    transcodingLiveStreamingConfig.streamID = streamID; // 设置 stream id，该 id 为合流任务的唯一标识符
    transcodingLiveStreamingConfig.publishUrl = @"publish url"; // 设置合流任务的推流地址
    transcodingLiveStreamingConfig.width = 480; // 设置合流画布的宽度
    transcodingLiveStreamingConfig.height = 848; // 设置合流画布的高度
    transcodingLiveStreamingConfig.fps = 20; // 设置合流任务的视频帧率
    transcodingLiveStreamingConfig.fillMode = QNVideoFillModePreserveAspectRatioAndFill; // 设置合流任务的默认画面填充方式
    transcodingLiveStreamingConfig.bitrateBps = 1000; // 设置合流任务的码率，单位: kbps
    
    QNTranscodingLiveStreamingImage *backgroundImage = [[QNTranscodingLiveStreamingImage alloc] init];
    backgroundImage.frame = CGRectMake(0, 0, 480, 848);
    backgroundImage.imageUrl = @"http://xxxx";
    
    transcodingLiveStreamingConfig.background = backgroundImage; // 设置合流画布的背景图片，仅支持 HTTP
    transcodingLiveStreamingConfig.watermarks = @[backgroundImage]; // 设置合流任务的水印
    [rtcClient startLiveStreamingWithTranscoding:transcodingLiveStreamingConfig]; // 开始转推
    

合流转推任务创建成功后，会触发如下
[QNRTCClientDelegate.didStartLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStartLiveStreaming)
回调：

    
    
    - (void)RTCClient:(QNRTCClient *)client didStartLiveStreaming:(NSString *)streamID;
    

此时，可以在该回调接口中设置合流布局。

### 设置合流布局

合流转推任务创建成功之后，就可以基于用户发布的 Track 进行合流布局的配置了。这里首先需要了解下
[QNTranscodingLiveStreamingTrack](https://developer.qiniu.com/rtc/api/8863/QNTranscodingLiveStreamingTrack-
iOS) 的概念。

相关配置的示例代码如下：

    
    
    QNTranscodingLiveStreamingTrack *transcodingTrack = [[QNTranscodingLiveStreamingTrack alloc] init];
    transcodingTrack.trackID = trackID; // 设置待合流 Track id
    transcodingTrack.frame = CGRectMake(0, 0, 480, 848); // 设置 Track 画面在合流画面中位置的 x、y 及宽高的位置
    transcodingTrack.zOrder = 0; // 设置 Track 画面在合流画面中的层级，0 是最底层
    

> 音频 Track 和视频 Track 创建合流布局的方法相同，音频 Track 对应创建的
> [QNTranscodingLiveStreamingTrack](https://developer.qiniu.com/rtc/api/8863/QNTranscodingLiveStreamingTrack-
> iOS) 只需传入
> [trackID](https://developer.qiniu.com/rtc/8863/QNTranscodingLiveStreamingTrack-
> iOS#trackID) 即可。

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

    
    
    - (void)RTCClient:(QNRTCClient *)client didSubscribedRemoteVideoTracks:(NSArray<QNRemoteVideoTrack *> *)videoTracks audioTracks:(NSArray<QNRemoteAudioTrack *> *)audioTracks ofUserID:(NSString *)userID {
    	// 当成功订阅远端 Track 时会触发此回调
    }
    

通过调用下面的方法
[QNTranscodingLiveStreamingTrack](https://developer.qiniu.com/rtc/api/8698/QNTranscodingLiveStreamingTrack)
更新已有 [Track](https://developer.qiniu.com/rtc/quick_start/9909/the-rtc-basic-
concept#track) 的布局：

    
    
    - (void)setTranscodingLiveStreamingID:(NSString *)streamID withTracks:(NSArray <QNTranscodingLiveStreamingTrack *> *)tracks;
    

当期望取消某路合流布局时，可以通过调用
[QNRTCClient.removeTranscodingLiveStreamingID](https://developer.qiniu.com/rtc/api/8836/QNRTCClient-
iOS#removeTranscodingLiveStreamingID) 接口实现：

    
    
    - (void)removeTranscodingLiveStreamingID:(NSString *)streamID withTracks:(NSArray <QNTranscodingLiveStreamingTrack *> *)tracks;
    

## 停止合流直播

可以通过如下方式，调用
[QNRTCClient.stopLiveStreamingWithTranscoding](https://developer.qiniu.com/rtc/api/8836/QNRTCClient-
iOS#stopLiveStreamingWithTranscoding) 实现合流转推任务的停止

    
    
    [rtcClient stopLiveStreamingWithTranscoding:transcodingLiveStreamingConfig];
    

合流转推任务停止成功后，会触发
[QNRTCClientDelegate.didStopLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStopLiveStreaming)
回调：

    
    
    - (void)RTCClient:(QNRTCClient *)client didStopLiveStreaming:(NSString *)streamID;
    

# 单路流、多路流合流二者切换的场景

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

为了避免切换过程中断流黑屏的问题，这里我们七牛直播云引入 `serialnum` 的概念，支持 `serialnum`
决定流的优先级，值越大，优先级越高，可以帮助更好的实现两路流的平滑切换：

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

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

  1. 创建单路流转推任务，同时进行单路流直播
  2. 需要从单路转推任务切换到合流转推任务时，`创建自定义合流任务`，注意要使用自定义合流任务指定带有 `serialnum` 参数的推流地址，在收到合流转推任务的 [didStartLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStartLiveStreaming) 回调之后，在回调中执行 `[rtcClient stopLiveStreamingWithDirect:directLiveStreamingConfig]` 来停止单路转推任务
  3. 需要从合流转推任务切换到单路转推任务时，创建单路转推任务，其推流地址需要带有 `serialnum` 参数，在收到单路转推任务的 [didStartLiveStreaming](https://developer.qiniu.com/rtc/api/9248/QNRTCClientDelegate#didStartLiveStreaming) 回调之后，在回调中执行 `[rtcClient stopLiveStreamingWithTranscoding:transcodingLiveStreamingConfig]` 来停止合流转推任务

通过上述方式，即可实现单路流直播、多路流合流直播之间的切换，具体实现也可参照 [牛互动 Demo](https://github.com/pili-
engineering/QNRTCLive-
iOS/blob/master/QNRTCLiveDemo/QNRTCLiveDemo/QNLiveViewController.m) 中的相关实现

# 发送 SEI

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

    
    
    [self.cameraVideoTrack sendSEIWithData:@"SEI Message" uuid:@"123456789" repeatCount:@1];
    [self.caustomVideoTrack sendSEIWithData:@"SEI Message" uuid:@"123456789" repeatCount:@1];
    [self.screenVideoTrack sendSEIWithData:@"SEI Message" uuid:@"123456789" repeatCount:@1];
    

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

# 注意事项

  * CDN 转推需要配置本地或者远端的音视频 Track，因此，**调用转推接口前请务必保证加入了房间，并且已经发布或者订阅了相应的音视频 Track**
  * **单路流直播场景，一路流仅支持一路音频轨和一路视频轨的设置，重复设置会被覆盖**
  * **如果场景涉及到单路流直播、多路流合流直播之间的切换，那么合流任务务必使用自定义合流任务以指定带有`serialnum` 的推流地址。其中，serialnum 决定流的优先级，从 1 开始递增，值越大，优先级越高**

# 示例代码

CDN 转推场景的示例代码可参考 [API-Examples-iOS](https://github.com/pili-engineering/QNRTC-
iOS/blob/master/QNRTC-API-Examples/Api-Examples-iOS/Module/CDN%20Streaming)

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