连麦 PK
场景概述
主播连麦 PK 场景指的是主播在直播时,可以对另外一个直播间的主播发起 PK 挑战,一旦挑战被接受,两个直播间的主播就会加入到同一个房间,并开始进行连麦互动。
与常规 1v1 连麦场景不同的是,PK 场景下直播界面会一分为二,每位主播各自的粉丝观看链接不会改变,但是可以同时看到两位主播的画面。
实现分析
纯直播切换到 PK 场景
主播 A 在直播中,收到主播 B 的 PK 邀请。
主播 A 首先需要离开当前的直播房间,但不能更改合流配置的 mergeJob id 以及推流地址,然后主动加入主播 B 的房间,与主播 B 进行连麦。
此时,主播 B 需要修改合流界面布局的配置,将自己的画面位置布局在分屏的左边,将对方(主播 A)的画面位置布局在分屏的右边。
同时,主播 A 则需要重新创建合流任务,注意要使用原先的 mergeJob id 以及推流地址,然后修改合流的布局,从原来的画面全屏,改为将自己的画面位置设置在分屏的左边,将主播 B 的画面位置设置在分屏的右边,最后配置 layout 布局。
这样,主播 B 是观众看到的画面是主播 B 在左边,主播 A 在右边。
而主播 A 的观众不需要更换拉流地址,看到的是主播 A 在左边,主播 B 在右边。
PK 场景切换到纯直播
主播 A 与主播 B 在 PK 连麦直播中,需要结束 PK 的模式。
主播 A 退出主播 B 所在房间,与此同时,主播 B 及时修改画面布局,从左右分屏的布局,改为自己画面全屏布局。
主播 A 在离开主播 B 的所在房间后,及时进入自己的原房间,重新创建合流任务,注意要使用原先的 mergeJob id 以及推流地址,然后修改合流的布局,从左右分屏布局,改为自己画面全屏布局。
这样,主播 A 的观众不需要更换拉流地址,看到主播 A 画面全屏;主播 B 的观众看到主播 B 画面全屏。
代码参考
QNMergeJob
无论是主播 A 还是主播 B,都需要维护一个全局的 QNMergeJob
,操作示例代码如下:
创建 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());
主播 A 操作流程
退出当前房间
- 主播 A 在接受 PK 邀请后,需要停止当前合流,并退出当前房间:
mEngine.stopMergeStream(mCurrentMergeJob.getMergeJobId());
mEngine.leaveRoom();
- 成功退出房间后,会触发如下回调接口,主播 A 可以在该回调内重新加入主播 B 的房间:
public void onRoomLeft() {
// 成功离开房间,可以重新加入指定房间
}
加入主播 B 的房间
主播 A 在离开自己的房间后,便可以获取主播 B 房间的 token 并加入。当主播 A 成功加入主播 B 的房间后,需要重新创建合流任务,同时需要对自己和主播 B 的合流布局进行配置。具体步骤可分解如下:
成功加入房间:可根据
onRoomStateChanged
回调监听是否成功加入房间,详情可参考房间管理创建合流任务:成功加入房间后,需要在适当的时机创建合流任务,合流任务和纯直播时保持一致即可,尤其是推流地址,切换地址会影响观众端的拉流体验,因此,建议维护一个全局的合流任务实例
设置合流布局:SDK 提供了
本地成功发布音视频
以及远端成功发布音视频
的回调接口,详情可参考 QNRTCEngineEventListener,收到音视频成功发布的回调后,在确保合流任务创建成功的前提下,可以进行合流画面的布局的配置,从纯直播布局切换为 PK 模式布局,并设置生效直播 PK:合流布局配置成功后,便可以进行正常的主播间 PK 了,切换房间的过程对观众端基本没有明显的影响
退出主播 B 的房间
当 PK 完成后,主播 A 可以回到自己的直播间,操作流程和上述基本一致,唯一的区别是合流布局存在差异,基本流程如下:
- 停止合流,退出主播 B 的房间
- 加入自己的房间
- 重新发布音视频 track
- 重新创建合流任务
- 重新配置合流布局(配置为纯直播场景的布局)
在上述操作后,主播 A 便可以恢复正常直播了
主播 B 操作流程
主播 B 仅需要监听主播 A 加入房间的动作,并适当调整配置相应的合流布局即可,示例代码如下:
@Override
public void onRemotePublished(String remoteUserId, List<QNTrackInfo> trackInfoList) {
// 主播 A 加入房间并发布音视频后,重新设置直播布局为 PK 模式的布局
}
@Override
public void onRemoteUnpublished(final String remoteUserId, List<QNTrackInfo> trackInfoList) {
// 主播 A 取消发布音视频并退出房间后,重新设置直播布局为纯直播模式
}
上述代码仅供参考,具体监听的回调需要根据您的业务场景进行适当的调整,更详细的回调说明请参考 QNRTCEngineEventListener
注意事项
- 离开房间再进入房间,必须要重新创建合流任务,再配置合流布局,否则会导致合流失败布局超时。
- 在 PK 场景下,请使用自定义合流任务,否则可能会出现合流任务冲突的情况。
- 务必确保在创建合流成功的情况下,再设置合流布局,否则会合流失败。
- 业务逻辑上管理好相应的 mergeJobId 以及转推流地址,保证 pk 逻辑的正常实现。
- 配置合流布局时,分音频 track 和视频 track,若合流中既要音频也要视频,需要都配置传入。
- 配置合流布局 layout 信息时,务必对应好 trackInfo 的类型,防止布局视频 track 时类型异常,进而导致合流黑屏。
- 需要及时更新 layouts 布局,否则可能会出现合流画面不符合预期设置的问题。