CDN 转推
本部分介绍了 CDN 转推的使用姿势及其应用场景。
应用场景
CDN 转推可实现直播场景的功能,实时音视频场景下的直播主要包括三个部分:单路流直播、多路流合流直播以及两者结合可切换的直播场景。
下面将会就三种场景的的使用姿势进行说明。
实现分析
设置监听
在进行 CDN 转推之前,需要设置 CDN 转推流的状态监听:
// 设置监听
virtual void SetLiveStreamingListener(QNLiveStreamingListener* listener) = 0;
// 监听接口类
class QNLiveStreamingListener
{
public:
/**
* 转推任务成功创建时触发此回调
*
* @param stream_id 转推成功的 stream id
*/
virtual void OnStarted(const std::string& stream_id) = 0;
/**
* 转推任务成功停止时触发此回调
*
* @param stream_id 停止转推的 stream id
*/
virtual void OnStopped(const std::string& stream_id) = 0;
/**
* 转推任务配置更新时触发此回调
*
* @param stream_id 配置更新的 stream id
*/
virtual void OnTranscodingTracksUpdated(const std::string& stream_id) = 0;
/**
* 转推任务出错时触发此回调
* @param stream_id 出现错误的 stream id
* @param error_info 详细错误原因
*/
virtual void OnError(const std::string& stream_id, const QNLiveStreamingErrorInfo& error_info) = 0;
protected:
virtual ~QNLiveStreamingListener() {}
};
其中,转推任务出错时的错误原因可参考 QNLiveStreamingErrorInfo
在设置好监听后,便可以基于业务场景进行单路转推任务
或者合流转推任务
的创建了。
单路流直播场景
单路流直播的场景,顾名思义,就是将一条音视频流直接转推到直播服务器,主要适用于不包含连麦的秀场直播
、连麦中需要将某一路流单独转推落存储
等场景。
场景示意图如下:
注意:如果主播有两路视频流(采集+录屏)需要合流转推,请参考多路流合流直播场景实现
单路流转推场景主要实现步骤如下:
创建单路转推任务
QNDirectLiveStreamingConfig 用于配置单路转推的相关信息,包括推流地址、参与 CDN 转推的音视频轨。
创建转推任务的示例代码如下:
qiniu::QNDirectLiveStreamingConfig config;
// 设置 stream id,该 id 为合流任务的唯一标识符
config.stream_id = _custom_forward_id;
// 设置推流地址
config.publish_url = "rtmp://pili-publish.qnsdk.com/sdk-live/window-forward";
// 设置单路流中的视频轨,仅支持一路视频的设置,重复设置会被覆盖
config.local_video_track = _camera_track_ptr;
// 设置单路流中的音频轨,仅支持一路音频的设置,重复设置会被覆盖
config.local_audio_track = _microphone_audio_track_ptr;
// 开始进行单路转推
client->StartLiveStreaming(config);
单路转推任务创建成功后,会触发上述 QNLiveStreamingListener.OnStarted
回调接口,回调该接口即代表成功开启了单路流转推,可以通过相应的播放链接拉取直播流进行观看。
注意:
- QNDirectLiveStreamingConfig 仅支持配置一路视频轨和一路音频轨,重复设置会被覆盖
停止单路转推任务
可以通过如下方式实现单路转推任务的停止:
client->StopLiveStreaming(config);
单路转推任务停止成功后,会触发上述 QNLiveStreamingListener.OnStopped
回调接口。
多路流合流直播场景
多路流合流直播场景,主要适用于连麦互动直播
、PK 直播
以及单主播需要两路以上视频合流转推
等场景。简单来说,就是对连麦各方的视频画面进行合流,然后转推。这种场景相较于纯直播场景的单路流转推会复杂一些。
场景示意图如下:
为了实现该场景,首先,需要了解下相关配置类及其作用:
- QNTranscodingLiveStreamingConfig: 用于配置合流的基本参数,包括任务 id、推流地址、合流的宽高、码率等信息。
- QNTranscodingLiveStreamingTrack: 用于配置参与 CDN 合流的每一路媒体 track 在合流画布中的位置、大小等信息。
- QNTranscodingLiveStreamingImage: 用于配置合流背景、水印配置参数。
了解上述概念后,该场景的主要实现步骤如下:
开启合流直播
创建 QNTranscodingLiveStreamingConfig
qiniu::QNTranscodingLiveStreamingConfig config;
config.stream_id = unicode2utf(_room_name.GetBuffer()) + "_merge";; // 设置 stream id,该 id 为合流任务的唯一标识符
config.publish_url = _merge_config.publish_url;; // 设置合流任务的推流地址
config.width = _merge_config.job_width; // 设置合流画布的宽度
config.height = _merge_config.job_height; // 设置合流画布的高度
config.fps = _merge_config.job_fps; // 设置合流任务的视频帧率
config.stretch_mode = _merge_config.job_stretch_mode; // 设置合流任务的默认画面填充方式
config.bitrate = _merge_config.job_bitrate; // 设置合流任务的码率,单位: kbps
config.merge_background = background; // 设置合流画布的背景图片,仅支持 HTTP
config.merge_watermark.emplace_back(mark); // 设置合流任务的水印
client->StartLiveStreaming(config); // 开始转推
合流任务创建成功后,会触发上述 QNLiveStreamingListener.OnStarted
回调接口。可以在该回调接口中设置合流布局
设置合流布局
合流任务创建成功之后,就可以基于用户发布的 track 进行合流布局的配置了。这里首先需要了解 QNTranscodingLiveStreamingTrack 的概念。操作示例代码如下:
qiniu::QNTranscodingLiveStreamingTrack merge_opt;
merge_opt.track_id = _camera_track_ptr->GetTrackID(); // 设置待合流 track id
merge_opt.x = _merge_config.local_video_x; // 设置 track 画面在合流画面中位置的 x 轴坐标
merge_opt.y = _merge_config.local_video_y; // 设置 track 画面在合流画面中位置的 y 轴坐标
merge_opt.z = 1; // 设置 track 画面在合流画面中的 zOrder 层级
merge_opt.width = _merge_config.local_video_width; // 设置 track 画面在合流画面中位置宽度
merge_opt.height = _merge_config.local_video_height; // 设置 track 画面在合流画面中位置高度
其中,远端用户的 track id 可以通过 SDK 提供的相关回调返回的 QNRemoteAudioTrack 和 QNRemoteVideoTrack 获取:
class QNClientEventListener {
public:
// 当成功订阅远端 track 时会触发此回调
virtual void OnSubscribed(const std::string& remote_user_id,const RemoteAudioTrackList& remote_audio_track_list,const RemoteVideoTrackList& remote_video_track_list) = 0;
}
通过上述代码创建 QNTranscodingLiveStreamingTrack 或者更新了已有的 track 布局配置后,就可以进行布局的配置了:
/**
* 添加合流的 track
*
* @param stream_id 合流任务 id
* @param transcoding_track_list 增加的 track 合流配置信息
*/
virtual void SetTranscodingLiveStreamingTracks(std::string& stream_id, QNTranscodeingTrackList& transcoding_track_list) = 0;
当期望取消某路合流布局时,可以通过如下调用实现:
/**
* 删除合流中的 track
*
* @param stream_id 合流任务 id
* @param transcoding_track_list 删除的 track
*/
virtual void RemoveTranscodingLiveStreamingTracks(std::string& stream_id, QNTranscodeingTrackList& transcoding_track_list) = 0;
停止合流直播
可以通过如下方式实现合流转推任务的停止:
client->StopLiveStreaming(config);
合流转推任务停止成功后,会触发上述 QNLiveStreamingListener.OnStopped
回调接口。
单路流、多路流合流二者切换的场景
单路流、多路流合流二者切换的场景,主要适用于有连麦需求的秀场直播
等场景,能够满足主播在自己单路流直播和连麦两路流合流直播二者间切换的需求。对于该场景的实现,需要注意的问题是,在两种场景切换的过程中,如何保证观看端不会断流黑屏。
为了避免切换过程中断流黑屏的问题,这里我们引入 serialnum
的概念以实现两路流的平滑切换:
- QNDirectLiveStreamingConfig 和 QNTranscodingLiveStreamingConfig 两种任务场景推流地址需要保持一致以避免播放端需要实现多余的切流操作
- 由于上述完全一致的地址可能会导致抢流的现象出现,所以需要在推流地址后面加上
serialnum
的参数,如 "rtmp://domain/app/streamName?serialnum=xxx",其中,serialnum 决定流的优先级,值越大,优先级越高,便不会出现抢流的现象。也基于此,合流任务必须使用自定义合流任务,以便自定义推流地址。
综上,单路流、合流切换场景的实现步骤如下:
- 创建单路流转推任务,同时进行单路流直播
- 需要从单路转推任务切换到合流转推任务时,
创建自定义合流任务
,注意要使用自定义合流任务指定带有serialnum
参数的推流地址,在收到合流转推任务的OnStarted
回调之后,在回调中执行client->StopLiveStreaming(direct_config)
来停止单路转推任务 - 需要从合流转推任务切换到单路转推任务时,创建单路转推任务,其推流地址需要带有
serialnum
参数,在收到单路转推任务的OnStarted
回调之后,在回调中执行_rtc_client_ptr->StopLiveStreaming(transcoding_config)
来停止合流转推任务
注意事项
- 如果场景涉及到单路流直播、多路流合流直播之间的切换,那么合流任务务必使用自定义合流任务以指定带有
serialnum
的推流地址。其中,serialnum 决定流的优先级,值越大,优先级越高 - 单路流直播场景,一路流仅支持一路音频轨和一路视频轨的设置,重复设置会被覆盖