一、简介
使用TRTCSDK直播时,如果角色都是大主播、小主播,类似会议场景,每个角色都是参与者,且人数较少(30以内),彼此通过渲染对方的view,来实现一屏多画面;
如果角色里面还有观众,且人数在几百至上万,就推荐使用MCU混流功能,调用混流接口实现混合画面,旁路推流出去,提供给观众观看一屏多画面的功能。
TRTC目前提供了两种混流方式:云端api混流、终端api混流。
本篇主要介绍终端混流方案,实现下图这种混流方式。demo下载链接
默认大画面是大主播,小主播进房连麦后,仍然大画面显示大主播,右下第一个小画面是自己的本地画面。
注意: 云端混流转码需要对输入 MCU 集群的音视频流进行解码后重新编码输出,将产生额外的服务成本,因此 TRTC 将向使用 MCU 集群进行云端混流转码的用户收取额外的增值费用。云端混流转码费用根据转码输出的分辨率大小和转码时长进行计费,转码输出的分辨率越高、转码输出的时间越长,费用越高。详情请参见云端混流转码计费说明。
二、api介绍
参考api文档描述:
setMixTranscodingConfig()
onSetMixTranscodingConfig()
使用 TRTC SDK 发起混流指令非常简单,只需调用各个平台的setMixTranscodingConfig()API 即可,混流结果会通过onSetMixTranscodingConfig()回调出来。
目前 SDK 提供了 4 种常用的混流方案:
参数项 | 纯音频模式(PureAudio) | 预排版模式(PresetLayout) | 屏幕分享模式(ScreenSharing) | 全手动模式(Manual) |
---|---|---|---|---|
调用次数 | 只需调用一次接口 | 只需调用一次接口 | 只需调用一次接口 | 以下场景需调用混流接口:有连麦者加入时有连麦者离开时连麦者开关摄像头时连麦者开关麦克风时 |
混合内容 | 只混合音频 | 自定义设置各路内容 | 不混合学生端的画面 | 自定义设置各路内容 |
audioSampleRate | 推荐48000 | 推荐48000 | 推荐48000 | 推荐48000 |
audioBitrate | 推荐64 | 推荐64 | 推荐64 | 推荐64 |
audioChannels | 推荐2 | 推荐2 | 推荐2 | 推荐2 |
videoWidth | 无需设置 | 不能为0 | 推荐0 | 不能为0 |
videoHeight | 无需设置 | 不能为0 | 推荐0 | 不能为0 |
videoBitrate | 无需设置 | 不能为0 | 推荐0 | 不能为0 |
videoFramerate | 无需设置 | 推荐15 | 推荐15 | 推荐15 |
videoGOP | 无需设置 | 推荐3 | 推荐3 | 推荐3 |
mixUsers 数组 | 无需设置 | 使用占位符设置 | 无需设置 | 使用真实 userId 设置 |
目前示例demo中,演示了预排版模式和全手动模式 预排版模式不会触发onSetMixTranscodingConfig()回调,全手动模式每次调用混流,都会触发onSetMixTranscodingConfig()
三、全手动模式代码示例
0、demo操作示例
混流需要三个身份:TRTC主播、TRTC观众、CDN观众,这就需要直播间管理逻辑:在成员进房、退房,上麦、下麦时调用混流接口
直播通话的房间管理功能,参考sdk包中的SimpleDemo的live模块,搭建了一个简单后台服务,用于增删改查房间列表。
线上功能,切不可使用simpleDemo中的后台服务,很简单,仅供demo演示用
全手动模式下,我们需要设置TRTCTranscodingConfig中的所有参数,并需要监听 TRTCCloud 中的onUserVideoAvailable()和onUserAudioAvailable()回调,以便根据当前房间中各个上麦用户的音视频状态不断地调整mixUsers参数,否则会导致混流失败。
代码语言:javascript复制//目前示例demo中,仅演示监听onUserVideoAvailable(),根据视频位调整混流。
@Override
public void onUserVideoAvailable(String userId, boolean available) {
int index = mRemoteUidList.indexOf(userId);
Log.i(TAG, "onUserVideoAvailable index " index ", available " available " userId " userId);
if (available) {
if (index == -1 && !userId.equals(mRoomId)) { //找不到
mRemoteUidList.add(userId);
refreshRemoteVideoViews();
if(isMixTransCodeManual&&isAnchor()){
MixTranscodeUtils.mixTransCodeManual(mTRTCCloud,mRoomId,mRemoteUidList);
}
} else if (userId.equals(mRoomId)) {
mTRTCCloud.startRemoteView(userId, mAnchorPreviewView);
mBigPreviewMuteVideoDefault.setVisibility(View.GONE);
}
} else {
if (index != -1 && !userId.equals(mRoomId)) { //找到
// 关闭用户userId的视频画面
mTRTCCloud.stopRemoteView(userId);
mRemoteUidList.remove(index);
refreshRemoteVideoViews();
if(isMixTransCodeManual&&isAnchor()){
MixTranscodeUtils.mixTransCodeManual(mTRTCCloud,mRoomId,mRemoteUidList);
}
} else if (userId.equals(mRoomId)) {
mBigPreviewMuteVideoDefault.setVisibility(View.VISIBLE);
}
}
}
1、双人混流
双人混流完整示例代码如下,运行效果如上截图。
代码语言:javascript复制背景颜色0x61B9F1(蓝色),可以换成png背景图片
public class MixTranscodeUtils {
private static void mixTransCodeManualTwo(TRTCCloud mTRTCCloud, String roomId,List<String> subUserList) {
int mainWidth = 270;
int mainHeight = 480;
int mainOffsetX = 2;
int mainOffsetY = 160;
TRTCCloudDef.TRTCTranscodingConfig config = new TRTCCloudDef.TRTCTranscodingConfig();
config.appId = GenerateTestUserSig.APPID;
config.bizId = GenerateTestUserSig.BIZID;
config.videoWidth = 544;
config.videoHeight = 960;
config.videoGOP = 1;
config.videoFramerate = 15;
config.videoBitrate = 1300;
config.backgroundColor = 0x61B9F1;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 1;
config.mode = TRTCCloudDef.TRTC_TranscodingConfigMode_Manual;
config.mixUsers = new ArrayList<>();
TRTCCloudDef.TRTCMixUser oneMixUser = new TRTCCloudDef.TRTCMixUser();
oneMixUser.roomId = roomId;
oneMixUser.zOrder = 1;
oneMixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
oneMixUser.width = mainWidth;
oneMixUser.height = mainHeight;
oneMixUser.userId = roomId;
oneMixUser.x = mainOffsetX;
oneMixUser.y = mainOffsetY;
TRTCCloudDef.TRTCMixUser twoMixUser = new TRTCCloudDef.TRTCMixUser();
twoMixUser.roomId = roomId;
twoMixUser.zOrder = 2;
twoMixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
twoMixUser.width = mainWidth;
twoMixUser.height = mainHeight;
twoMixUser.userId = subUserList.get(0);;
twoMixUser.x = mainOffsetX;
twoMixUser.y = mainOffsetY;
config.mixUsers.add(oneMixUser);
config.mixUsers.add(twoMixUser);
mTRTCCloud.setMixTranscodingConfig(config);
}
}
2、三人混流
三人混流完整示例代码如下,运行效果如下截图。
代码语言:javascript复制public class MixTranscodeUtils {
private static void mixTransCodeManualThree(TRTCCloud mTRTCCloud, String roomId,List<String> subUserList) {
int mainWidth = 270;
int mainHeight = 360;
int mainOffsetX = 137;
int mainOffsetY = 80;
TRTCCloudDef.TRTCTranscodingConfig config = new TRTCCloudDef.TRTCTranscodingConfig();
config.appId = GenerateTestUserSig.APPID;
config.bizId = GenerateTestUserSig.BIZID;
config.videoWidth = 544;
config.videoHeight = 960;
config.videoGOP = 1;
config.videoFramerate = 15;
config.videoBitrate = 1300;
config.backgroundColor = 0x61B9F1;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 1;
config.mode = TRTCCloudDef.TRTC_TranscodingConfigMode_Manual;
config.mixUsers = new ArrayList<>();
TRTCCloudDef.TRTCMixUser oneMixUser = new TRTCCloudDef.TRTCMixUser();
oneMixUser.roomId = roomId;
oneMixUser.zOrder = 1;
oneMixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
oneMixUser.width = mainWidth;
oneMixUser.height = mainHeight;
oneMixUser.userId = roomId;
oneMixUser.x = mainOffsetX;
oneMixUser.y = mainOffsetY;
TRTCCloudDef.TRTCMixUser twoMixUser = new TRTCCloudDef.TRTCMixUser();
twoMixUser.roomId = roomId;
twoMixUser.zOrder = 2;
twoMixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
twoMixUser.width = mainWidth;
twoMixUser.height = mainHeight;
twoMixUser.userId = subUserList.get(0);;
twoMixUser.x = 2;
twoMixUser.y = mainOffsetY mainHeight;
TRTCCloudDef.TRTCMixUser threeMixUser = new TRTCCloudDef.TRTCMixUser();
threeMixUser.roomId = roomId;
threeMixUser.zOrder = 3;
threeMixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
threeMixUser.width = mainWidth;
threeMixUser.height = mainHeight;
threeMixUser.userId = subUserList.get(1);;
threeMixUser.x = 2 mainWidth;
threeMixUser.y = mainOffsetY mainHeight;
config.mixUsers.add(oneMixUser);
config.mixUsers.add(twoMixUser);
config.mixUsers.add(threeMixUser);
mTRTCCloud.setMixTranscodingConfig(config);
}
}
3、混流参数思考
可以看到,混流的参数虽多,却非常好理解: 1、首先设置画布大小和一些公共参数, 2、然后依次设置每个主播画面的大小、位置,把每个主播的画面位置参数添加到configList里面去, 3、最后setMixTranscodingConfig(configList)即可。
如上代码,除去参数多需要注意而外,主要花精力的地方,就是布局参数问题。
已知混流界面是以左上角为原点,X轴向右递增,Y轴向下递增。
我们将画布设置成常见的544X960分辨率,然后各个画面也设置成常见的9:16小分辨率(或3:4小分辨率),按一定的间隔摆在画布上即可。
为了避免重复代码,将公共参数放入一个方法中,下面多人混流示例中,将不再展示完整混流参数。
代码语言:javascript复制//设置画布公共参数
public static TRTCCloudDef.TRTCTranscodingConfig setCanvasQuality(int videoNum , int mixMode) {
TRTCCloudDef.TRTCTranscodingConfig config = new TRTCCloudDef.TRTCTranscodingConfig();
config.appId = GenerateTestUserSig.APPID;
config.bizId = GenerateTestUserSig.BIZID;
config.videoWidth = 544;
config.videoHeight = 960;
config.videoGOP = 1;
config.videoFramerate = 15;
config.videoBitrate = 1200 videoNum * 50;
config.backgroundColor = 0x61B9F1;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 1;
config.mode = mixMode;
config.mixUsers = new ArrayList<>();
return config;
}
//设置混流大画面公共参数
public static List<TRTCCloudDef.TRTCMixUser> initMainMixUser(String roomId,
int mainWidth, int mainHeight, int num) {
List<TRTCCloudDef.TRTCMixUser> mainUserList = new ArrayList<>();
for (int i = 0; i < num; i ) {
TRTCCloudDef.TRTCMixUser mixUser = new TRTCCloudDef.TRTCMixUser();
mixUser.roomId = roomId;
mixUser.zOrder = i 1;
mixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
mixUser.width = mainWidth;
mixUser.height = mainHeight;
mainUserList.add(mixUser);
}
return mainUserList;
}
//设置混流小画面公共参数
public static List<TRTCCloudDef.TRTCMixUser> initSubMixUser(String roomId,
int subWidth, int subHeight, int mainNum, int subNum) {
List<TRTCCloudDef.TRTCMixUser> subUserList = new ArrayList<>();
for (int i = 0; i < subNum; i ) {
TRTCCloudDef.TRTCMixUser mixUser = new TRTCCloudDef.TRTCMixUser();
mixUser.roomId = roomId;
mixUser.zOrder = mainNum i 1;
mixUser.streamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
mixUser.width = subWidth;
mixUser.height = subHeight;
subUserList.add(mixUser);
}
return subUserList;
}
4、四人混流
四人混流示例代码如下,运行效果如下截图。
代码语言:javascript复制static int mixMode1 = TRTCCloudDef.TRTC_TranscodingConfigMode_Manual;
private static void mixTransCodeManualFour(TRTCCloud mTRTCCloud, String roomId,List<String> subUserList) {
int mainWidth = 270;
int mainHeight = 480;
int mainOffsetX = 2;
int mainOffsetY = 0;
TRTCCloudDef.TRTCTranscodingConfig config = setCanvasQuality(4,mixMode1);
List<TRTCCloudDef.TRTCMixUser> mixUsers = initMainMixUser(roomId,mainWidth, mainHeight, 4);
TRTCCloudDef.TRTCMixUser trtcMixUser1 = mixUsers.get(0);
TRTCCloudDef.TRTCMixUser trtcMixUser2 = mixUsers.get(1);
TRTCCloudDef.TRTCMixUser trtcMixUser3 = mixUsers.get(2);
TRTCCloudDef.TRTCMixUser trtcMixUser4 = mixUsers.get(3);
trtcMixUser1.userId = roomId;
trtcMixUser1.x = mainOffsetX;
trtcMixUser1.y = mainOffsetY;
trtcMixUser2.userId = subUserList.get(0);
trtcMixUser2.x = mainOffsetX mainWidth;
trtcMixUser2.y = mainOffsetY;
trtcMixUser3.userId = subUserList.get(1);
trtcMixUser3.x = mainOffsetX;
trtcMixUser3.y = mainOffsetY mainHeight;
trtcMixUser4.userId = subUserList.get(2);
trtcMixUser4.x = mainOffsetX mainWidth;
trtcMixUser4.y = mainOffsetY mainHeight;
config.mixUsers.add(trtcMixUser1);
config.mixUsers.add(trtcMixUser2);
config.mixUsers.add(trtcMixUser3);
config.mixUsers.add(trtcMixUser4);
mTRTCCloud.setMixTranscodingConfig(config);
}
5、五人混流
五人混流运行效果如下截图,代码如下。
代码语言:javascript复制private static void mixTransCodeManualFive(TRTCCloud mTRTCCloud,String roomId, List<String> subUserList) {
int mainWidth = 270;
int mainHeight = 480;
int mainOffsetX = 2;
int mainOffsetY = 40;
int subWidth = 180;
int subHeight = 320;
TRTCCloudDef.TRTCTranscodingConfig config = setCanvasQuality(5,mixMode1);
List<TRTCCloudDef.TRTCMixUser> mainMixUsers = initMainMixUser(roomId,mainWidth, mainHeight, 2);
TRTCCloudDef.TRTCMixUser trtcMixUser1 = mainMixUsers.get(0);
TRTCCloudDef.TRTCMixUser trtcMixUser2 = mainMixUsers.get(1);
List<TRTCCloudDef.TRTCMixUser> subMixUsers = initSubMixUser(roomId,subWidth, subHeight, 2, 3);
TRTCCloudDef.TRTCMixUser trtcMixUser3 = subMixUsers.get(0);
TRTCCloudDef.TRTCMixUser trtcMixUser4 = subMixUsers.get(1);
TRTCCloudDef.TRTCMixUser trtcMixUser5 = subMixUsers.get(2);
trtcMixUser1.userId = roomId;
trtcMixUser1.x = mainOffsetX;
trtcMixUser1.y = mainOffsetY;
trtcMixUser2.userId = subUserList.get(0);
trtcMixUser2.x = mainOffsetX mainWidth;
trtcMixUser2.y = mainOffsetY;
trtcMixUser3.userId = subUserList.get(1);
trtcMixUser3.x = mainOffsetX;
trtcMixUser3.y = mainOffsetY mainHeight;
trtcMixUser4.userId = subUserList.get(2);
trtcMixUser4.x = mainOffsetX subWidth;
trtcMixUser4.y = mainOffsetY mainHeight;
trtcMixUser5.userId = subUserList.get(3);
trtcMixUser5.x = mainOffsetX subWidth subWidth;
trtcMixUser5.y = mainOffsetY mainHeight;
config.mixUsers.add(trtcMixUser1);
config.mixUsers.add(trtcMixUser2);
config.mixUsers.add(trtcMixUser3);
config.mixUsers.add(trtcMixUser4);
config.mixUsers.add(trtcMixUser5);
mTRTCCloud.setMixTranscodingConfig(config);
}
6、六人混流
六人混流运行效果如下截图,代码如下。
代码语言:javascript复制private static void mixTransCodeManualSix(TRTCCloud mTRTCCloud, String roomId,List<String> subUserList) {
int mainWidth = 360;
int mainHeight = 640;
int mainOffsetX = 2;
int mainOffsetY = 0;
int subWidth = 180;
int subHeight = 320;
TRTCCloudDef.TRTCTranscodingConfig config = setCanvasQuality(6,mixMode1);
List<TRTCCloudDef.TRTCMixUser> mainMixUsers = initMainMixUser(roomId,mainWidth, mainHeight, 1);
TRTCCloudDef.TRTCMixUser trtcMixUser1 = mainMixUsers.get(0);
trtcMixUser1.userId = roomId;
trtcMixUser1.x = mainOffsetX;
trtcMixUser1.y = mainOffsetY;
List<TRTCCloudDef.TRTCMixUser> subMixUsers = initSubMixUser(roomId,subWidth, subHeight, 1, 5);
TRTCCloudDef.TRTCMixUser trtcMixUser2 = subMixUsers.get(0);
TRTCCloudDef.TRTCMixUser trtcMixUser3 = subMixUsers.get(1);
TRTCCloudDef.TRTCMixUser trtcMixUser4 = subMixUsers.get(2);
TRTCCloudDef.TRTCMixUser trtcMixUser5 = subMixUsers.get(3);
TRTCCloudDef.TRTCMixUser trtcMixUser6 = subMixUsers.get(4);
trtcMixUser2.userId = subUserList.get(0);
trtcMixUser2.x = mainOffsetX mainWidth;
trtcMixUser2.y = mainOffsetY;
trtcMixUser3.userId = subUserList.get(1);
trtcMixUser3.x = mainOffsetX mainWidth;
trtcMixUser3.y = mainOffsetY subHeight;
trtcMixUser4.userId = subUserList.get(2);
trtcMixUser4.x = mainOffsetX;
trtcMixUser4.y = mainOffsetY mainHeight;
trtcMixUser5.userId = subUserList.get(3);
trtcMixUser5.x = mainOffsetX subWidth;
trtcMixUser5.y = mainOffsetY mainHeight;
trtcMixUser6.userId = subUserList.get(4);
trtcMixUser6.x = mainOffsetX subWidth subWidth;
trtcMixUser6.y = mainOffsetY mainHeight;
config.mixUsers.add(trtcMixUser1);
config.mixUsers.add(trtcMixUser2);
config.mixUsers.add(trtcMixUser3);
config.mixUsers.add(trtcMixUser4);
config.mixUsers.add(trtcMixUser5);
config.mixUsers.add(trtcMixUser6);
mTRTCCloud.setMixTranscodingConfig(config);
}
7、七人混流
七人混流运行效果如下截图,代码如下。
代码语言:javascript复制private static void mixTransCodeManualSeven(TRTCCloud mTRTCCloud, String roomId,List<String> subUserList) {
int mainWidth = 360;
int mainHeight = 480;
int mainOffsetX = 92;
int mainOffsetY = 0;
int subWidth = 180;
int subHeight = 240;
TRTCCloudDef.TRTCTranscodingConfig config = setCanvasQuality(7,mixMode1);
List<TRTCCloudDef.TRTCMixUser> mainMixUser = initMainMixUser(roomId,mainWidth, mainHeight, 1);
TRTCCloudDef.TRTCMixUser trtcMixUser1 = mainMixUser.get(0);
trtcMixUser1.userId = roomId;
trtcMixUser1.x = mainOffsetX;
trtcMixUser1.y = mainOffsetY;
List<TRTCCloudDef.TRTCMixUser> subMixUsers = initSubMixUser(roomId,subWidth, subHeight, 1, 6);
TRTCCloudDef.TRTCMixUser trtcMixUser2 = subMixUsers.get(0);
TRTCCloudDef.TRTCMixUser trtcMixUser3 = subMixUsers.get(1);
TRTCCloudDef.TRTCMixUser trtcMixUser4 = subMixUsers.get(2);
TRTCCloudDef.TRTCMixUser trtcMixUser5 = subMixUsers.get(3);
TRTCCloudDef.TRTCMixUser trtcMixUser6 = subMixUsers.get(4);
TRTCCloudDef.TRTCMixUser trtcMixUser7 = subMixUsers.get(5);
trtcMixUser2.userId = subUserList.get(0);
trtcMixUser2.x = 2;
trtcMixUser2.y = mainOffsetY mainHeight;
trtcMixUser3.userId = subUserList.get(1);
trtcMixUser3.x = 2 subWidth;
trtcMixUser3.y = mainOffsetY mainHeight;
trtcMixUser4.userId = subUserList.get(2);
trtcMixUser4.x = 2 subWidth subWidth;
trtcMixUser4.y = mainOffsetY mainHeight;
trtcMixUser5.userId = subUserList.get(3);
trtcMixUser5.x = 2;
trtcMixUser5.y = mainOffsetY mainHeight subHeight;
trtcMixUser6.userId = subUserList.get(4);
trtcMixUser6.x = 2 subWidth;
trtcMixUser6.y = mainOffsetY mainHeight subHeight;
trtcMixUser7.userId = subUserList.get(5);
trtcMixUser7.x = 2 subWidth subWidth;
trtcMixUser7.y = mainOffsetY mainHeight subHeight;
config.mixUsers.add(trtcMixUser1);
config.mixUsers.add(trtcMixUser2);
config.mixUsers.add(trtcMixUser3);
config.mixUsers.add(trtcMixUser4);
config.mixUsers.add(trtcMixUser5);
config.mixUsers.add(trtcMixUser6);
config.mixUsers.add(trtcMixUser7);
mTRTCCloud.setMixTranscodingConfig(config);
}
四、预排版代码示例
上面全手动模式下,每次混流都可以调整布局参数,实现不同的布局风格。
当然这样灵活性更高,只是代码繁琐一点,需要注意onUserVideoAvailable()和onUserAudioAvailable()回调处理逻辑。
实际线上玩法,有时并不需要复杂的布局,只需要简单的嵌套大小画面即可,这时候就推荐使用预排版模式了。
预排版模式更加简单: 1、进房前设置好布局模板 2、没有2,只上面一步就到位了
预排版混流,实现嵌套画面,代码示例和实现的混流效果如下:
代码语言:javascript复制public static void mixTransCodeAuto(TRTCCloud mTRTCCloud,String roomId) {
int mainWidth = 544;
int mainHeight = 960;
int mainOffsetX = 0;
int mainOffsetY = 0;
int subWidth = 120;
int subHeight = 160;
int subOffsetX = 32;
int subOffsetY = 120;
TRTCCloudDef.TRTCTranscodingConfig config = setCanvasQuality(2,mixMode3);
// 设置混流后主播的画面位置
List<TRTCCloudDef.TRTCMixUser> mainUserList = initMainMixUser(roomId,mainWidth, mainHeight, 1);
TRTCCloudDef.TRTCMixUser mainMixUser = mainUserList.get(0);
mainMixUser.userId = "$PLACE_HOLDER_LOCAL_MAIN$"; // 以主播uid为broadcaster为例
mainMixUser.x = mainOffsetX;
mainMixUser.y = mainOffsetY;
config.mixUsers.add(mainMixUser);
List<TRTCCloudDef.TRTCMixUser> subMixList = initSubMixUser(roomId,subWidth, subHeight, 1, 6);
for (int i = 0; i < 6; i ) {
TRTCCloudDef.TRTCMixUser _mixUser = subMixList.get(i);
_mixUser.userId = "$PLACE_HOLDER_REMOTE$";
if (i < 3) {
// 前三个小画面靠右从下往上铺
_mixUser.x = videoWidth - subOffsetX - subWidth;
_mixUser.y = (subOffsetY subHeight) * (2 - i) subOffsetY;
_mixUser.width = subWidth;
_mixUser.height = subHeight;
} else if (i >= 3 && i < 6) {
// 后三个小画面靠左从下往上铺
_mixUser.x = subOffsetX;
_mixUser.y = (subOffsetY subHeight) * (5-i) subOffsetY;
_mixUser.width = subWidth;
_mixUser.height = subHeight;
} else {
// 最多只叠加六个小画面
}
config.mixUsers.add(_mixUser);
}
mTRTCCloud.setMixTranscodingConfig(config);
}
五、补充说明
1、开启旁路推流
混流是对每一路视频流进行操作,所以首先得有视频流streamId,这个streamId不是TRTC的音视频数据流概念,而是云直播音视频数据流概念,要将TRTC的音视频数据流旁推的云直播服务,有两种方式。
官网有介绍。
①、控制台全局旁推
如下图,在控制台打开全局旁推,那么TRTC通话时,会将每一个主播的音视频数据流,旁推到云直播服务上。
②、指定流id旁推
如下图,设置成指定流旁推,就不会默认旁推所有流了,必需在TRTCSDK中,用api申明这个主播要旁推。api写法如下
参与混流的每一个主播到要旁推
代码语言:javascript复制@Override
protected void enterRoom() {
// 初始化配置
mTRTCParams = new TRTCCloudDef.TRTCParams();
mTRTCParams.sdkAppId = GenerateTestUserSig.SDKAPPID;
mTRTCParams.userId = mUserId;
mTRTCParams.roomId = Integer.parseInt(mRoomId);
mTRTCParams.userSig = GenerateTestUserSig.genTestUserSig(mTRTCParams.userId);
//申明旁推,指定旁推streamId
mTRTCParams.streamId = GenerateTestUserSig.SDKAPPID "_" mRoomId "_" mUserId "_main";
// 开启本地声音采集并上行
mTRTCCloud.startLocalAudio();
// 开启本地画面采集并上行
mTRTCCloud.startLocalPreview(mIsFrontCamera, mAnchorPreviewView);
// 进入直播间
mTRTCCloud.enterRoom(mTRTCParams, TRTC_APP_SCENE_LIVE);
}
旁推成功了,在云直播控制台就能看到这条流id,并点开预览画面。如下图7条流都在,大主播的画面混流成功了。
2、CDN拉流
streamId已经旁推到云直播了,就可以按照云直播服务标准进行拉流操作了,要拉流就得有播放地址,播放地址拼接如官方文档所示:
拿到的播放地址,如果没有鉴权参数,就是标准的流媒体协议,可以放入VLC、SDK播放器中播放。
demo中是用移动直播sdk的播放器TXLivePlayer进行CDN播放的
3、混流中那些公共参数获取
不太好找的公共参数是:appid、bizid,它们在实时音视频控制台上可以看到。
4、历史版本问题
setMixTranscodingConfig终端混流接口,调用的混流服务叫MCU混流,是新开发的功能,您的SDKAPPID应用,如果开通比较早,是不支持MCU混流的,会出现调用接口失败or无响应。
解决办法是联系TX支持人员,给您开通一下MCU混流白名单。
六、demo下载地址
TestMixDemo