直播场景最佳实践
场景概述
实时音视频场景下的直播,主要分为三个种,它们分别是单路流直播、多路流合流直播以及两者相结合可切换的直播场景。
以下将对上述三种场景的使用姿势做相应的使用说明。
实现分析
单路流直播场景
单路流直播场景,就是将一路音视频流通过 RTN 服务器直接转推到直播服务器,适用于不包含连麦的秀场直播
、连麦时需要将某路流单独转推落存储
等场景。
该场景的流程示意图大致如下:
注意:若主播有一路以上视频流(采集/外部导入),需要做合流转推,可参考多路流合流直播场景的实现。
单路流转推场景主要实现步骤如下:
创建单路转推任务
ForwardOptInfo
用于配置单路转的相关信息,包括推流地址、jobId以及音视频 track
创建转推任务的示例代码如下:
qiniu_v2::ForwardOptInfo forwardInfo;
forwardInfo.audio_only = false;
// 是否使用七牛内部转推,默认为 true
forwardInfo.is_internal = true;
forwardInfo.job_id = _custom_forward_id;
forwardInfo.publish_url = "rtmp://pili-publish.qnsdk.com/sdk-live/window-forward";
_forward_audio_flag = false;
_forward_video_flag = false;
for (auto&& itor : _local_tracks_list) {
// 这里 forwardInfo 仅支持配置一路音频和一路视频
if (itor->GetKind().compare("audio") == 0 && !_forward_audio_flag) {
_forward_audio_flag = true;
forwardInfo.track_id_list.emplace_back(itor->GetTrackId());
}
if (itor->GetKind().compare("video") == 0 && !_forward_video_flag) {
_forward_video_flag = true;
forwardInfo.track_id_list.emplace_back(itor->GetTrackId());
}
}
if (_rtc_room_interface) {
_rtc_room_interface->CreateForwardJob(forwardInfo);
_contain_forward_flag = true;
}
单路转推任务创建成功后,会回调以下接口:
// 创建单路转推任务结果反馈
// @param job_id_ 单路转推的任务 id
// @param error_code_ 0:成功, 非 0: 失败
// @param error_str_ error_code_ 非 0 时的错误描述信息
virtual void OnCreateForwardResult(
const std::string& job_id_,
int error_code_,
const std::string& error_str_
) = 0;
创建成功即开启了单路流转推,可以通过相应的播放链接拉取直播流进行观看。
注意: 1.ForwardOptInfo 仅支持配置一路视频 Track 和一路音频 Track,多个或重复设置会被覆盖
停止单路转推任务
可以通过调用如下 API 实现单路转推任务的停止:
// 停止单路转推任务
// @param job_id 单路转推任务 id
// @return 0:操作成功,具体转推结果请通过观看旁路直播进行查看
virtual int StopForwardJob(const string& job_id) = 0;
需要传入对应的 jobId
多路流合流直播场景
多路流合流直播场景,适用于连麦互动直播
、PK 直播
以及单主播需两路以上视频合流转推
等场景。
简单来说,就是将连麦各方的音视频进行合流,然后进行转推。相对于单路转推会更复杂些。
该场景的流程示意图大致如下:
实现该场景,需要先了解下相关配置类及其作用:
- 合流在
qiniu::QNRoomInterface
接口中定义,具体接口可参考QNRoomInterface - 合流具体步骤请参考合流配置
单路流转推、多路流合流两者的切换
单路流转推加上多路流合流的切换场景,适用于存在连麦需求的秀场直播
等场景,它能够满足主播单路流直播、连麦合流直播的在直播过程中有切换的需求。
该场景的实现,需要注意如何在切换过程中,保证观看端不会出现断流黑屏。
为避免切换过程中的断流黑屏问题,我们引入 serialnum
的概念来实现两路流的平滑切换。
需要注意以下几点:
- 单路流转推和多路流合流两种任务场景的推流地址需要保持一致,以避免播放端多余的切流操作
- 由于以上提到的完全一致的推流地址,可能会出现抢流的现象出现,所以需要在推流地址上加上
serialnum
的参数,如"rtmp://xxx.com/app/roomName?serialnum=xxx" - serialnum 决定流的优先级,值越大,优先级越高,不会出现抢流的现象。
- 由于需要自定义推流地址,故合流任务必须使用自定义合流任务。
综上所述,单路流转推、多路流合流切换的场景的实现步骤大致如下:
- 创建单路转推任务,同时开启单路流直播
- 需要从单路流转推切换到多路流合流转推时,
创建自定义合流任务
,注意要使用自定义合流任务指定带有serialnum
参数的推流地址,在收到
void OnStopMergeResult(
const std::string& job_id_,
const std::string& job_iid_,
int error_code_,
const std::string& error_str_
);
回调之后在回调中执行
int StopForwardJob(const string& job_id);
来停止单路转推任务
- 需要从合流转推任务切换到单路转推任务时,创建单路转推任务,其推流地址需要带有
serialnum
参数,在收到
void OnStopForwardResult(
const std::string& job_id_,
const std::string& job_iid_,
int error_code_,
const std::string& error_str_
);
回调之后在回调中执行
int StopMergeStream(const string& job_id = string());
来停止合流转推任务
通过上述方式,即可实现单路流直播、多路流合流直播之间的切换,具体实现也可参照 Win32 Demo 以及 SDK 下载地址 中的相关实现
注意事项
如果场景涉及到单路流直播、多路流合流直播之间的切换,那么合流任务务必使用自定义合流任务以指定带有
serialnum
的推流地址。其中,serialnum 决定流的优先级,值越大,优先级越高单路流直播场景,一路流仅支持一路音频轨和一路视频轨的设置,多路或重复设置会被覆盖