跳到主要内容

合流布局

5.1.1 版本(RCRTCMixConfig#getVersion() == 2)开始,RCRTCMixConfig 新增 setCustomMode(自定义模式开关)。开启后可更灵活地控制合流布局,建议设为 true。新版本兼容旧版本逻辑,升级 SDK 无需修改代码。

画布和声音配置

  1. 画布指多路视频流新合成后的视频背景宽高。无论采用何种合流布局,均在画布宽高范围内渲染。此配置为可选;如未指定,则默认宽高为 360 * 640,帧率为 25。

    Java
    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 方法的场景说明:

    Java
    /**
    *
    * 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)

Java
/**
* 创建自定义合流布局配置
* @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)

Java
/**
* 创建悬浮布局合流配置
* @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)

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

合流布局设置

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

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

参数说明

属性类型说明
mixConfigRCRTCMixConfig合流配置信息
Java
/**
* 设置合流布局
*/
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();
}
}
});
}

音频合流

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

  • 示例代码:

    Java
    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) {

    }
    });