旁路推流画面布局

更新时间: 2023/01/17 08:34:55

配置旁路推流任务时,您可以自定义房间画面的各路视频布局方式,例如调整整体画布大小和颜色、各路视频的图像大小、位置等。本文档为您介绍视频布局的设置方式和推荐设置。

限制说明

  • 用户窗口边界不能超出整体画布。
  • 视频互动的画面布局中,最多 7 人参与;纯语音互动最多 21 人。

设置画面布局

您可以选择通过客户端的旁路推流相关接口的 layout 参数或者服务端 RESTful API 设置旁路推流的画面布局,服务端设置旁路推流画面布局的方法请参考旁路推流画面布局。移动客户端受限于网络状况,为保证直播的稳定性,建议通过服务端实现旁路推流。本文档为您展示通过客户端设置旁路推流画面布局的实现方式。

背景画布

通过 NERtcLiveStreamLayout 类的 width 等字段设置混流视频的背景画布属性,包括背景画布的高度、宽度和颜色。

相关字段的具体说明如下:

参数名称
类型
描述
width int 整体画布的宽度,单位为 px。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。整体画布的高度与宽度的乘积不得大于 1920*1080。
height int 整体画布的高度,单位为 px。
取值范围为 0 ~ 1920。若设置为奇数值,会自动向下取偶。整体画布的高度与宽度的乘积不得大于 1920*1080。

backgroundColor

int

画面背景颜色,默认为 0,即黑色。支持以下格式的颜色码:

  • 256 ✖ 256 ✖ R + 256 ✖ G + B 的和。请将对应 RGB 的值分别带入此公式计算即可。
  • 十六进制颜色码,即 #RRGGBB 或 RRGGBB 格式。例如 #CC00FF。

用户画面

通过 NERtcLiveStreamLayout 类的 userTranscodingList 参数设置混流视频中每个参与者对应的画面属性。

参数名称
类型
描述
uid long 将指定uid对应用户的视频流拉入直播。
如果添加多个 users,则 uid 不能重复。
x int 通过 x 和 y 指定画布坐标中的一个点,该点将作为用户图像的左上角。
x 参数用于设置画布的横轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
y int 通过 x 和 y 指定画布坐标中的一个点,该点将作为用户图像的左上角。
y 参数用于设置画布的纵轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。

zOrder

int

直播视频上用户视频帧的图层编号。取值范围为 0 ~ 100。

  • 最大值为 100,表示该区域图像位于最上层。
  • 最小值为 0(默认值),表示该区域图像位于最下层。
width int 该用户图像在画布中的宽度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
height int 该用户图像在画布中的高度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。

adaption

int

用于设置占位图片和指定区域的适应属性。可设置为:

  • kNERtcLsModeVideoScaleFit(默认):适应图片。即保证视频内容全部显示,未覆盖区域默认填充背景色。
  • kNERtcLsModeVideoScaleCropFill:适应区域。即保证所有区域被填满,视频超出部分会被裁剪。

audioPush

boolean

是否在直播中混流该用户的对应音频流。可设置为:

  • true(默认):在直播中混流该用户的对应音频流。
  • false:在直播中将该用户设置为静音。

videoPush

boolean

是否在直播中向观看者播放该用户的对应视频流。可设置为:

占位图片

通过 NERtcLiveStreamLayout 类的 backgroundImgList 参数设置混流视频中的占位图片属性,包括占位图片的位置、URL 等。

  • 支持设置最多 6 张图片。
  • 您可以通过 NERtcLiveConfiginterruptedPlaceImage 字段选择是否开启此功能;若设置为关闭,则此设置无效。
  • backgroundImg 字段仍保留,仅可设置一张占位图,若您同时配置了两个字段,则以 backgroundImgList 配置为准。
参数名称 类型 描述
url String 占位图片的 URL。
x int 通过 x 和 y 指定画布坐标中的一个点,该点将作为占位图片的左上角。
x 参数用于设置画布的横轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
y int 通过 x 和 y 指定画布坐标中的一个点,该点将作为占位图片的左上角。
y 参数用于设置画布的纵轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
width int 该占位图片在画布中的宽度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
height int 该占位图片在画布中的高度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。

zOrder

int

该占位图的图层编号。取值范围为 0 ~ 100。

  • 最大值为 100,表示该区域图像位于最上层。
  • 最小值为 0(默认值),表示该区域图像位于最下层。

布局示例

本节为您介绍如何通过客户端 addLiveStreamTask 接口的 layout 参数设置旁路推流画面布局。

请求示例

在本示例中,音视频房间中有两位主播/连麦者,其推流画面布局为横向左右均分布局,原始画布为深灰色,其中一人掉线后显示占位图片。

示例代码如下:

// 加入房间前设置直播模式
NERtcEx.getInstance().setChannelProfile(1);

// 加入房间后添加推流任务
NERtcLiveStreamTaskInfo liveTask1 = new NERtcLiveStreamTaskInfo();
liveTask1.taskId = String.valueOf(Math.abs(rtmp://test.url.hashCode()));
liveTask1.url = rtmp://test.url;
liveTask1.serverRecordEnabled = false;
liveTask1.liveMode = enableVideo? NERtcLiveStreamTaskInfo.NERtcLiveStreamMode.kNERtcLsModeVideo;

//设置整体布局
NERtcLiveStreamLayout layout = new NERtcLiveStreamLayout();
layout.userTranscodingList = new ArrayList<>(); 
layout.backgroundImgList = new ArrayList<>(); 
layout.width = 720;
layout.height = 640;
layout.backgroundColor = Color.parseColor(#8421504);
liveTask1.layout = layout;

// 设置左边成员布局
NERtcLiveStreamUserTranscoding user1 = new NERtcLiveStreamUserTranscoding();
user1.uid = 66601; //
user1.audioPush = true;
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
    user1.x = 0;
    user1.y = 0;
    user1.width = 360; 
    user1.height = 640; 
    user1.zOrder = 1;
}

layout.userTranscodingList.add(user1);

// 设置右边成员布局
NERtcLiveStreamUserTranscoding user2 = new NERtcLiveStreamUserTranscoding();
user2.uid = 66602;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
        user2.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user2.x = 360;
        user2.y = 0;
        user2.width = 360;
        user2.height = 640;
        user2.zOrder = 1;
    }
layout.userTranscodingList.add(user2);

//设置音视频流编码参数
NERtcLiveConfig config = new NERtcLiveConfig();
config.interruptedPlaceImage = true;
config.singleVideoPassThrough = true;
config.audioBitrate = 64 kbps;
config.sampleRate = NERtcLiveStreamAudioSampleRate48000;
config.audioCodecProfile= NERtcLiveStreamAudioCodecProfileLCAAC;
config.channels = 2;
layout.config = config;

//设置占位图片布局
NERtcLiveStreamImageInfo image1 = new NERtcLiveStreamImageInfo();
image1.url = www.163.com/test.jpg;
image1.x = 360;
image1.y = 0;
image1.width = 360;
image1.height = 640;
image1.zOrder = 0;
layout.backgroundImgList.add(image1);

// 调用 addLiveStreamTask 接口添加推流任务
int ret = NERtcEx.getInstance().addLiveStreamTask(liveTask1, addLiveTaskCallback);
if (ret != 0) {
        showToast("调用添加推流任务接口执行失败 , ret : " + ret);
    }

// 添加推流任务的异步callback
private AddLiveTaskCallback addLiveTaskCallback = new AddLiveTaskCallback(){
void onAddLiveStreamTask(String taskId, int errCode){
    if (code == RtcCode.LiveCode.OK) {
            showToast("添加推流任务成功 : taskId " + taskId);
        } else {
            showToast("添加推流任务失败 : taskId " + taskId + " , code : " + code);
        }
    }
};

效果展示

  • 原始画布:

    原始画布

  • 增加占位图片:

    增加占位图片

  • 正常显示画面:

    正常显示画面

  • 右侧用户断线:

    右侧用户断线

  • 左侧用户断线:

    左侧用户断线

常用布局设置

互动直播支持自定义配置视频布局,您也可以参考以下典型的常用布局配置,优化您的自定义布局。

双人横向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout layout = new NERtcLiveStreamLayout();
layout.userTranscodingList = new ArrayList<>(); 
layout.backgroundImgList = new ArrayList<>(); 
layout.width = 640;
layout.height = 360;
layout.backgroundColor = Color.parseColor(#0x808080);
liveTask1.layout = layout;

// 设置左边成员布局
NERtcLiveStreamUserTranscoding user1 = new NERtcLiveStreamUserTranscoding();
user1.uid = 66601; //
user1.audioPush = true;
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
    user1.x = 0;
    user1.y = 0;
    user1.width = 320; 
    user1.height = 360; 
    user1.zOrder = 1;
}

layout.userTranscodingList.add(user1);

// 设置右边成员布局
NERtcLiveStreamUserTranscoding user2 = new NERtcLiveStreamUserTranscoding();
user2.uid = 66602;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
        user2.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user2.x = 320;
        user2.y = 0;
        user2.width = 320;
        user2.height = 360;
        user2.zOrder = 1;
    }
layout.userTranscodingList.add(user2);

三人纵向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout layout = new NERtcLiveStreamLayout();
layout.userTranscodingList = new ArrayList<>(); 
layout.backgroundImgList = new ArrayList<>(); 
layout.width = 360;
layout.height = 640;
layout.backgroundColor = Color.parseColor(#0x808080);
liveTask1.layout = layout;

// 设置上方成员布局
NERtcLiveStreamUserTranscoding user1 = new NERtcLiveStreamUserTranscoding();
user1.uid = 123; //
user1.audioPush = true;
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
    user1.x = 0;
    user1.y = 0;
    user1.width = 360; 
    user1.height = 320; 
    user1.zOrder = 1;
}

layout.userTranscodingList.add(user1);

// 设置左下成员布局
NERtcLiveStreamUserTranscoding user2 = new NERtcLiveStreamUserTranscoding();
user2.uid = 456;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
        user2.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user2.x = 0;
        user2.y = 320;
        user2.width = 180;
        user2.height = 320;
        user2.zOrder = 1;
    }
layout.userTranscodingList.add(user2);

// 设置右下成员布局
NERtcLiveStreamUserTranscoding user3 = new NERtcLiveStreamUserTranscoding();
user3.uid = 789;
user3.audioPush = true;
user3.videoPush = enableVideo;
if (user3.videoPush) {
        user3.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user3.x = 180;
        user3.y = 320;
        user3.width = 180;
        user3.height = 320;
        user3.zOrder = 1;
    }
layout.userTranscodingList.add(user3);

1 + N 悬浮布局

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout layout = new NERtcLiveStreamLayout();
layout.userTranscodingList = new ArrayList<>(); 
layout.backgroundImgList = new ArrayList<>(); 
layout.width = 360;
layout.height = 640;
layout.backgroundColor = Color.parseColor(#0x808080);
liveTask1.layout = layout;

// 设置上方成员布局
NERtcLiveStreamUserTranscoding user1 = new NERtcLiveStreamUserTranscoding();
user1.uid = 123; //
user1.audioPush = true;
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
    user1.x = 0;
    user1.y = 0;
    user1.width = 360; 
    user1.height = 640; 
    user1.zOrder = 1;
}

layout.userTranscodingList.add(user1);

// 设置左下成员布局
NERtcLiveStreamUserTranscoding user2 = new NERtcLiveStreamUserTranscoding();
user2.uid = 456;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
        user2.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user2.x = 45;
        user2.y = 390;
        user2.width = 110;
        user2.height = 213;
        user2.zOrder = 1;
    }
layout.userTranscodingList.add(user2);

// 设置右下成员布局
NERtcLiveStreamUserTranscoding user3 = new NERtcLiveStreamUserTranscoding();
user3.uid = 789;
user3.audioPush = true;
user3.videoPush = enableVideo;
if (user3.videoPush) {
        user3.adaption = NERtcLiveStreamUserTranscoding.NERtcLiveStreamVideoScaleMode.kNERtcLsModeVideoScaleCropFill;
        user3.x = 185;
        user3.y = 390;
        user3.width = 110;
        user3.height = 213;
        user3.zOrder = 1;
    }
layout.userTranscodingList.add(user3);
此文档是否对你有帮助?
有帮助
去反馈
  • 限制说明
  • 设置画面布局
  • 背景画布
  • 用户画面
  • 占位图片
  • 布局示例
  • 请求示例
  • 效果展示
  • 常用布局设置
  • 双人横向平铺
  • 三人纵向平铺
  • 1 + N 悬浮布局