直播场景最佳实践
场景概述
实时音视频场景下的直播主要包括三个部分:单路流直播、多路流合流直播以及两者结合可切换的直播场景。
下面将会就三种场景的的使用姿势进行说明。
实现分析
单路流直播场景
单路流直播的场景,顾名思义,就是将一条音视频流直接转推到直播服务器,主要适用于不包含连麦的秀场直播
、连麦中需要将某一路流单独转推落存储
等场景。
场景示意图如下:
注意:如果主播有两路视频流(采集+录屏)需要合流转推,请参考多路流合流直播场景实现
单路流转推场景主要实现步骤如下:
创建单路转推任务
QNForwardJob 用于配置单路转推的相关信息,包括推流地址、参与合流的音视频轨,详细的接口设置可参考 QNForwardJob。
创建转推任务的示例代码如下:
// 创建单路转推任务对象
mForwardJob = new QNForwardJob();
// 设置 ForwardJob id
mForwardJob.setForwardJobId(mRoomName);
// 设置推流地址
mForwardJob.setPublishUrl(String.format(getString(R.string.publish_url), mRoomName));
// 设置单路流中的音频轨,仅支持一路音频的设置,重复设置会被覆盖
mForwardJob.setAudioTrack(mLocalAudioTrackInfo);
// 设置单路流中的视频轨,仅支持一路视频的设置,重复设置会被覆盖
mForwardJob.setVideoTrack(mLocalCameraTrackInfo);
// 创建单路流转推任务
mEngine.createForwardJob(mForwardJob);
单路转推任务创建成功后,会触发如下回调接口:
/**
* 当单路流转推任务创建成功的时候会回调此方法
*
* @param forwardJobId 转推任务 ID
*/
@Override
public void onCreateForwardJobSuccess(String forwardJobId) {
// forwardJobId 即为创建成功的任务 id
ToastUtils.s(RoomActivity.this, "单路转推任务 " + forwardJobId + " 创建成功!");
}
创建成功即开启了单路流转推,可以通过相应的播放链接拉取直播流进行观看
注意:
1. QNForwardJob 仅支持配置一路视频轨和一路音频轨,重复设置会被覆盖
2. 单路转推的场景下,务必保证配置了 "固定分辨率" QNRTCSetting#setMaintainResolution
选项的开启,否则会出现不可预期的问题!!!
停止单路转推任务
可以通过如下方式实现单路转推任务的停止:
mEngine.stopForwardJob(mForwardJob.getForwardJobId());
多路流合流直播场景
多路流合流直播场景,主要适用于连麦互动直播
、PK 直播
以及单主播需要两路以上视频合流转推
等场景。简单来说,就是对连麦各方的视频画面进行合流,然后转推。这种场景相较于纯直播场景的单路流转推会复杂一些。
场景示意图如下:
为了实现该场景,首先,需要了解下相关配置类及其作用:
QNMergeJob :
用于配置合流的基本参数,包括任务 id、推流地址、合流的宽高、码率等信息。具体接口可参考 QNMergeJobQNMergeTrackOption:
用于配置每一路媒体 track 在合流画布中的位置、大小等信息。具体接口可参考 QNMergeTrackOption
了解上述概念后,该场景的主要实现步骤如下:
开启合流直播
创建 QNMergeJob
// 创建合流任务对象
if (mCurrentMergeJob == null) {
mCurrentMergeJob = new QNMergeJob();
}
// 设置合流任务 id,该 id 为合流任务的唯一标识符
mCurrentMergeJob.setMergeJobId(customMergeJobId);
// 设置合流任务的推流地址,该场景下需保持一致
mCurrentMergeJob.setPublishUrl(publishUrl);
mCurrentMergeJob.setWidth(width);
mCurrentMergeJob.setHeight(height);
// QNMergeJob 中码率单位为 bps,所以,若期望码率为 1200kbps,则实际传入的参数值应为 1200 * 1000
mCurrentMergeJob.setBitrate(bitrate);
mCurrentMergeJob.setMinBitrate(minBitrate);
mCurrentMergeJob.setMaxBitrate(maxBitrate);
mCurrentMergeJob.setFps(fps);
mCurrentMergeJob.setStretchMode(stretchMode);
// 创建合流任务
mEngine.createMergeJob(mCurrentMergeJob);
合流任务创建成功后会触发如下回调接口:
@Override
public void onCreateMergeJobSuccess(String mergeJobId) {
// mergeJobId 即为创建成功的合流任务 id
}
设置合流布局
合流任务创建成功之后,就可以基于用户发布的 track 进行合流布局的配置了。这里首先需要了解 QNMergeTrackOption
的概念。操作示例代码如下:
QNMergeTrackOption option = new QNMergeTrackOption();
option.setTrackId(trackId)
option.setX(x);
option.setY(y);
option.setZ(z);
option.setWidth(width);
option.setHeight(height);
其中,trackId 可以通过 SDK 提供的相关回调返回的 QNTrackInfo
获取:
@Override
public void onLocalPublished(@NonNull List<QNTrackInfo> trackInfoList) {
}
@Override
public void onRemotePublished(String remoteUserId, List<QNTrackInfo> trackInfoList) {
}
通过上述代码创建 QNMergeTrackOption
之后,就可以进行布局的配置了:
/**
* 设置添加合流布局
*
* @param addedTracks 待配置的 QNMergeTrackOption 的列表
* @param jobId 合流任务 id
*/
mEngine.setMergeStreamLayouts(addedTrackOptions, mCurrentMergeJob.getMergeJobId());
当期望取消某路合流布局时,可以通过如下调用实现:
/**
* 设置取消合流布局
*
* @param addedTracks 待移除的 QNMergeTrackOption 的列表
* @param jobId 合流任务 id
*/
mEngine.removeMergeStreamLayouts(removedTrackOptions, mCurrentMergeJob.getMergeJobId());
停止合流直播
可以通过如下方式实现合流转推任务的停止:
mEngine.stopMergeStream(mCurrentMergeJob.getMergeJobId());
单路流、多路流合流二者切换的场景
单路流、多路流合流二者切换的场景,主要适用于有连麦需求的秀场直播
等场景,能够满足主播在自己单路流直播和连麦两路流合流直播二者间切换的需求。对于该场景的实现,需要注意的问题是,在两种场景切换的过程中,如何保证观看端不会断流黑屏。
为了避免切换过程中断流黑屏的问题,这里我们引入 serialnum
的概念以实现两路流的平滑切换:
QNForwardJob
和QNMergeJob
两种任务场景推流地址需要保持一致以避免播放端需要实现多余的切流操作- 由于上述完全一致的地址可能会导致抢流的现象出现,所以需要在推流地址后面加上
serialnum
的参数,如 "rtmp://domain/app/streamName?serialnum=xxx",其中,serialnum 决定流的优先级,值越大,优先级越高,便不会出现抢流的现象。也基于此,合流任务必须使用自定义合流任务,以便自定义推流地址。
综上,单路流、合流切换场景的实现步骤如下:
- 创建单路流转推任务,同时进行单路流直播
- 需要从单路转推任务切换到合流转推任务时,
创建自定义合流任务
,注意要使用自定义合流任务指定带有serialnum
参数的推流地址,在收到onCreateMergeJobSuccess
回调之后,在回调中执行mEngine.stopForwardJob(mForwardJob.getForwardJobId())
来停止单路转推任务 - 需要从合流转推任务切换到单路转推任务时,创建单路转推任务,其推流地址需要带有
serialnum
参数,在收到onCreateForwardJobSuccess
回调之后,在回调中执行mEngine.stopMergeStream(mCurrentMergeJob.getMergeJobId())
来停止合流转推任务
通过上述方式,即可实现单路流直播、多路流合流直播之间的切换,具体实现也可参照 demo 中的相关实现
注意事项
- 为保证单路流直播的质量,请务必开启 "固定分辨率"
QNRTCSetting#setMaintainResolution
的选项 - 如果场景涉及到单路流直播、多路流合流直播之间的切换,那么合流任务务必使用自定义合流任务以指定带有
serialnum
的推流地址。其中,serialnum 决定流的优先级,值越大,优先级越高 - 单路流直播场景,一路流仅支持一路音频轨和一路视频轨的设置,重复设置会被覆盖