跳到主要内容

合流布局

5.1.1 版本(RCRTCMixConfig#getVersion() == 2)开始,RCRTCMixConfig 中新增加了 setCustomMode 方法,功能为自定义模式开关,打开后,主播用户可以更加灵活的控制合流布局,建议将其设置为 true,新版本兼容老版本逻辑,升级 SDK 不需要修改代码。

画布和声音配置

  1. 画布指的是多道视频流新合成后视频背景宽高,不管哪种合流布局方式,都是基于画布宽高范围内渲染,此配置为可选设置。如不指定画布宽高则默认为 360 * 640 帧率为25。

    RCRTCMixConfig config = new RCRTCMixConfig();
    RCRTCMixConfig.MediaConfig mediaConfig = new RCRTCMixConfig.MediaConfig();
    config.setMediaConfig(mediaConfig);
    //视频输出配置
    RCRTCMixConfig.MediaConfig.VideoConfig videoConfig = new RCRTCMixConfig.MediaConfig.VideoConfig();
    mediaConfig.setVideoConfig(videoConfig);
    //大流视频的输出参数
    RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout normal = new RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout();
    videoConfig.setVideoLayout(normal);
    //推荐宽、高、帧率参数值可以通过默认视频流的配置获取,也可以根据实际需求来自定义设置
    //如不设置宽高值则服务端将使用默认宽高 360 * 640
    //例:发布的视频分辨率为720 * 1280,如果不设置则观众端看到的视频分辨率为 360 * 640,
    //所以如果想让观众端看到的视频分辨率和发布视频分辨率一致,则应从发布的视频流中获取分辨率配置并设置到 mediaConfig 中
    RCRTCVideoStreamConfig defaultVideoConfig = RCRTCEngine.getInstance().getDefaultVideoStream().getVideoConfig();
    int fps = defaultVideoConfig.getVideoFps().getFps();
    int width = defaultVideoConfig.getVideoResolution().getWidth();
    int height = defaultVideoConfig.getVideoResolution().getHeight();
    normal.setWidth(width); //视频宽
    normal.setHeight(height); //视频高
    normal.setFps(fps); //视频帧率
    //小流视频的输出参数和标准视频流设置方法是一样的,不同的只是输出参数
    //RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout tinyVideo = new RCRTCMixConfig.MediaConfig.VideoConfig.VideoLayout();
    //videoConfig.setTinyVideoLayout(tinyVideo);

    //设置渲染裁剪模式(可选)
    //裁剪模式共分为两种: VideoRenderMode.CROP/VideoRenderMode.WHOLE(默认)
    videoConfig.setExtend(new RCRTCMixConfig.MediaConfig.VideoConfig.VideoExtend(isCrop ? RCRTCMixConfig.VideoRenderMode.CROP : RCRTCMixConfig.VideoRenderMode.WHOLE));
    //音频输出配置(可选)
    //mediaConfig.setAudioConfig(new RCRTCMixConfig.MediaConfig.AudioConfig(32));
  2. 视频合流中和 RCRTCMixConfig#setCustomMode 方法场景介绍:

    /**
    *
    * 1.customMode 参数设置为 true 时:
    *
    * 1.1.当没有设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数时,房间中所有音频流会自动合并,观众能听到所有主播声音。
    *
    * 1.2.当设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数为没有数据的集合(new ArrayList<RCRTCMixConfig.CustomLayoutList.CustomMixAudio>(16);)时,不合并音频流,观众仅能听见本房间主播声音。
    *
    * 1.3.当设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数不为 空 时,会将{@link RCRTCMixConfig.CustomLayoutList.CustomMixAudio#setAudioStream(RCRTCStream)}设置的音频流合流到直播流中,观众就能听到合并的音频。
    *
    * 1.4.当没有设置{@link RCRTCMixConfig#setCustomLayouts(List)}参数时,且已经设置{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数,即按照合流布局合流。
    *
    * 1.5.当设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数为没有数据的集合(new ArrayList<CustomLayout>(16))时,所有人视频都不合流。观众仅能看见本地主播视频。
    *
    * 1.6.当已经设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数 且{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数为 SUSPENSION 或 ADAPTIVE 时,按传入的{@link
    * RCRTCMixConfig.CustomLayoutList.CustomLayout#setCustomLayouts(List)}视频流合流。
    *
    * 1.7.当已经设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数 且{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数为 CUSTOM 时,按传入的{@link
    * RCRTCMixConfig.CustomLayoutList.CustomLayout#setCustomLayouts(List)} 视频流和合流布局进行合流。
    *
    * 2.customMode 参数设置为 false 时:全部合并所有主播音频流,视频流合并逻辑按照{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)} 参数合并。如果参数 {@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)} 为 CUSTOM 时,视频合流逻辑按照设置的{@link RCRTCMixConfig#setCustomLayouts(List)}} 集合合并。
    *
    * @param customMode 默认true
    */
    config.setCustomMode(true);

合流布局

直播合流视频布局目前分为三种:1. 自定义布局;2. 悬浮布局(默认);3. 自适应布局.下面分别介绍布局效果。

自定义布局

提示

通过调用自定义布局接口可以设置合流视频整体尺寸,以及各个连麦者视图位置及大小。

如下图所示,合流布局是以像素方式,定义视频输出尺寸, 如图整体视频尺寸 宽*高 = 300 * 300 ;以整体作为画布,画布的原点(0,0)在左上角, 那么三个连麦主播的窗口相对原点的位置,及其宽度,高度值分别如图所示(相应的设置代码也可在直播布局的接口文档中查看布局实例代码):

(height=300)

/**
* 创建自定义合流布局配置
* @param isCrop 是否裁减画布
* @param stream1 必须为视频流
* @param stream2 必须为视频流
* @param stream3 必须为视频流
* @return
*/
public RCRTCMixConfig create_Custom_MixConfig(boolean isCrop,RCRTCStream stream1,RCRTCStream stream2,RCRTCStream stream3){
RCRTCMixConfig config = new RCRTCMixConfig();
//1. 设置自定义合流布局模式
config.setLayoutMode(MixLayoutMode.CUSTOM);

//2. 合流画布设置
...(请参照画布和声音配置示例代码)

//3. 假设以画布设置的宽高为 300 * 300为例(应以真实设置的宽高为准),设置每个视频流小窗口的坐标及宽高
ArrayList<CustomLayout> list = new ArrayList<>();
config.setCustomLayouts(list);
//user1的视频流
RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout1 = new RCRTCMixConfig.CustomLayoutList.CustomLayout();
list.add(videoLayout1);
videoLayout1.setVideoStream(stream1); // RCRTCStream#MediaType 必须是Video
videoLayout1.setX(70); //X 坐标
videoLayout1.setY(20); //Y 坐标
videoLayout1.setWidth(130); // 视频窗口的宽
videoLayout1.setHeight(80); // 视频窗口的高
//user2的视频流
RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout2 = new RCRTCMixConfig.CustomLayoutList.CustomLayout();
list.add(videoLayout2);
videoLayout2.setVideoStream(stream2); // RCRTCStream#MediaType 必须是Video
videoLayout2.setX(20); //X 坐标
videoLayout2.setY(100); //Y 坐标
videoLayout2.setWidth(120); // 视频窗口的宽
videoLayout2.setHeight(150); // 视频窗口的高
//user3的视频流
RCRTCMixConfig.CustomLayoutList.CustomLayout videoLayout3 = new RCRTCMixConfig.CustomLayoutList.CustomLayout();
list.add(videoLayout3);
videoLayout3.setVideoStream(stream3); // RCRTCStream#MediaType 必须是Video
videoLayout3.setX(160); //X 坐标
videoLayout3.setY(100); //Y 坐标
videoLayout3.setWidth(120); // 视频窗口的宽
videoLayout3.setHeight(150); // 视频窗口的高
return config;
}

悬浮布局

背景视频来源默认采用第一个加入房间的主播发布的视频或合流布局接口指定的 HostVideoStream 视频流,显示区域为整个合流视频,合流视频大小需要调用接口设置 mediaConfig(默认值是 360 * 640); 当连麦者依次加入时,按照下图显示的序列加载子视图: 当有人离开时,系统会自动按照现有主播加入房间的次序重新布局视图

(height=300)

/**
* 创建悬浮布局合流配置
* @param stream 当做背景的视频流
* @return
*/
public RCRTCMixConfig create_Suspension_MixConfig(RCRTCStream stream){
RCRTCMixConfig config = new RCRTCMixConfig();
//1. 设置悬浮合流布局模式
config.setLayoutMode(MixLayoutMode.SUSPENSION);

//2. 合流画布设置
...(请参照画布和声音配置示例代码)

//3. 设置当做背景的视频流
config.setHostVideoStream(stream);
return config;
}

自适应布局

视频的整体大小为默认值 360 * 640 或通过合流接口自定义;当有多人加入房间后,直播系统会按照具体人数平分整体视频区域,使之每个子视图加载区域大小一致;录制系统会按照参会者进入房间的次序依次把参会者图像加载在示意图的相应序号上。 当有人离开时,系统会自动按照现有主播加入房间的次序重新布局视图。

(height=300) (height=300) (height=300) (height=300)

/**
* 创建自适应布局合流配置
* @return
*/
public RCRTCMixConfig create_Adaptive_MixConfig(){
RCRTCMixConfig config = new RCRTCMixConfig();
//1. 设置自适应合流布局模式
config.setLayoutMode(MixLayoutMode.ADAPTIVE);
//2. 合流画布设置
...(请参照画布和声音配置示例代码)
return config;
}

合流布局设置

配置好合流布局参数后,主播端需要调用 publishDefaultLivetreams(final IRCRTCResultDataCallback<RCRTCLiveInfo> callBack) 回调返回的 RCRTCLiveInfo 类中的 setMixConfig() 方法即可进行布局合流设置。

  1. 合流布局的功能主要是定义直播间连麦后合流视频的布局方式,可以根据自身业务需求来定义多个连麦者的画面的布局样式。
  2. 接口调用时机可以在主播发布资源后的任意时刻。使用自定义布局时需要在房间有人加入和退出时分别调用,以便合流视频中的画面按照 APP 设计规则展示。
  3. 利用发布资源成功返回的 RCRTCLiveInfo 对象,调用 setMixConfig() 方法设置布局。

参数说明

属性类型说明
mixConfigRCRTCMixConfig合流配置信息
/**
* 设置合流布局
*/
public void setMixLayout(String str) {
RCRTCMixConfig config = null;
String text = "";

switch (str) {
case AnchorConfig.ADAPTIVE://自适应布局
List<RCRTCStream> streams = new ArrayList<>();
streams.add(RCRTCEngine.getInstance().getDefaultVideoStream());
text = AnchorConfig.ADAPTIVE;
if (mRtcRoom != null) {
for (RCRTCRemoteUser remoteUser : mRtcRoom.getRemoteUsers()) {
for (RCRTCInputStream stream : remoteUser.getStreams()) {
if (stream.getMediaType() == RCRTCMediaType.VIDEO
&& ((RCVideoInputStreamImpl) stream)
.getSubscribeState() == RCRTCSubscribeState.SUBSCRIBED) {
streams.add(stream);
}
}
}
}
config = RTCMixLayout.getInstance().create_Adaptive_MixConfig(); // 切换为自适应布局
break;
case AnchorConfig.CUSTOM: // 自定义布局
text = AnchorConfig.CUSTOM;
config = RTCMixLayout.getInstance().create_Custom_MixConfig(streams);
break;
case AnchorConfig.SUSPENSION: // 悬浮布局
text = AnchorConfig.SUSPENSION;
config = RTCMixLayout.getInstance().create_Suspension_MixConfig(RCRTCEngine.getInstance().getDefaultVideoStream()); // 切换为悬浮布局
break;
}
if (mLiveInfo == null) {
return;
}
final String finalText = text;
mLiveInfo.setMixConfig(config, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
try {
getView().onSetMixLayoutSuccess(finalText);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}

@Override
public void onFailed(RTCErrorCode rtcErrorCode) {
try {
getView().onSetMixLayoutFailed(rtcErrorCode);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}

音频合流

音频合流布局的原理就是通过控制输入源列表,设置输出音频配置,达到合并哪些音频流输出指定配置的音频流。设置音频合流列表后,观众订阅直播流,就会只听到音频合流列表中对应的主播。

  • 示例代码:

    RCRTCMixConfig config = new RCRTCMixConfig();
    List<RCRTCMixConfig.CustomLayoutList.CustomMixAudio> customMixAudioList = new ArrayList<>();
    RCRTCMixConfig.CustomLayoutList.CustomMixAudio customMixAudio = null;

    // RCRTCRoom 房间中有其他主播且发布了资源
    if (mRTCRoom != null && mRTCRoom.getRemoteUsers() != null && mRTCRoom.getRemoteUsers().size() > 0) {
    for (RCRTCRemoteUser remoteUser : mRTCRoom.getRemoteUsers()) {
    if (remoteUser.getStreams() != null && remoteUser.getStreams().size() > 0) {
    for (RCRTCInputStream inputStream : remoteUser.getStreams()) {
    if (inputStream.getMediaType() == RCRTCMediaType.AUDIO) {
    customMixAudio = new CustomMixAudio();
    customMixAudio.setAudioStream(inputStream);
    //添加需要合并的音频流
    customMixAudioList.add(customMixAudio);
    }
    }
    }
    }
    }
    /**
    *
    * 音频合流中和 `RCRTCMixConfig#setCustomMode` 方法场景介绍:
    *
    * 1. customMode 参数设置为 true 时:
    *
    * 1.1 当没有设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数时,房间中所有音频流会自动合并,观众能听到所有主播声音。
    *
    * 1.2 当设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数为没有数据的集合(new ArrayList<RCRTCMixConfig.CustomLayoutList.CustomMixAudio>(16);)时,不合并音频流,观众仅能听见本房间主播声音。
    *
    * 1.3 当设置{@link RCRTCMixConfig#setCustomMixAudio(List)}参数不为 空 时,会将{@link RCRTCMixConfig.CustomLayoutList.CustomMixAudio#setAudioStream(RCRTCStream)}设置的音频流合流到直播流中,观众就能听到合并的音频。
    *
    * 1.4 当没有设置{@link RCRTCMixConfig#setCustomLayouts(List)}参数时,且已经设置{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数,即按照合流布局合流。
    *
    * 1.5 当设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数为没有数据的集合(new ArrayList<CustomLayout>(16))时,所有人视频都不合流。观众仅能看见本地主播视频。
    *
    * 1.6 当已经设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数 且{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数为 SUSPENSION 或 ADAPTIVE 时,按传入的{@link
    * RCRTCMixConfig.CustomLayoutList.CustomLayout#setCustomLayouts(List)}视频流合流。
    *
    * 1.7 当已经设置{@link RCRTCMixConfig#setCustomLayouts(List)}}参数 且{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)}参数为 CUSTOM 时,按传入的{@link
    * RCRTCMixConfig.CustomLayoutList.CustomLayout#setCustomLayouts(List)} 视频流和合流布局进行合流。
    *
    * 2. customMode 参数设置为 false 时:全部合并所有主播音频流,视频流合并逻辑按照{@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)} 参数合并。如果参数 {@link RCRTCMixConfig#setLayoutMode(MixLayoutMode)} 为 CUSTOM 时,视频合流逻辑按照设置的{@link RCRTCMixConfig#setCustomLayouts(List)}} 集合合并。
    *
    * @param customMode 默认true
    */
    config.setCustomMode(true);
    // 传入需要合并的音频流数据
    config.setCustomMixAudio(customMixAudioList);
    // 开始设置混流布局配置
    rcRTCLiveInfo.setMixConfig(config, new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {

    }

    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {

    }
    });