Android

旁路推流画面布局

更新时间: 2023/01/17 08:52:35

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

限制说明

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

设置画面布局

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

背景画布

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

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

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

backgroundColor

NSUInteger

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

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

用户画面

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

参数名称
类型
描述
uid uint64_t 将指定 uid 对应用户的视频流拉入直播。
如果添加多个 users,则 uid 不能重复。

videoPush

BOOL

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

audioPush

BOOL

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

  • YES(默认):在直播中混流该用户的对应音频流。
  • NO:在直播中将该用户设置为静音。
x NSInteger 通过 x 和 y 指定画布坐标中的一个点,该点将作为用户图像的左上角。
x 参数用于设置画布的横轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
y NSInteger 通过 x 和 y 指定画布坐标中的一个点,该点将作为用户图像的左上角。
y 参数用于设置画布的纵轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
width NSInteger 该用户图像在画布中的宽度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
height NSInteger 该用户图像在画布中的高度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。

zOrder

NSInteger

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

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

adaption

NSInteger

用于设置视频画面和指定区域的适应属性。可设置为:

  • kNERtcLsModeVideoScaleFit:优先保证视频内容全部显示。因视频尺寸与显示视窗尺寸不一致造成的视窗未被填满的区域填充背景色。
  • kNERtcLsModeVideoScaleCropFill:优先保证视窗被填满。因视频尺寸与显示视窗尺寸不一致而多出的视频将被截掉。

占位图片

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

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

zOrder

NSInteger

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

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

布局示例

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

请求示例

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

示例代码如下:

objc// 加入房间前设置直播模式。
[NERtcEngine.sharedEngine setChannelProfile:kNERtcChannelProfileLiveBroadcasting];

//加入房间后添加推流任务
NERtcLiveStreamTaskInfo *info = [[NERtcLiveStreamTaskInfo alloc] init];
info.taskID = 123;    
info.streamURL = rtmp://test.url;   
info.serverRecordEnabled = NO;  
info.lsMode = kNERtcLsModeVideo;

//设置整体布局
NERtcLiveStreamLayout *layout = [[NERtcLiveStreamLayout alloc] init];
layout.width = 720;     
layout.height = 640;  
layout.backgroundColor = #8421504;
info.layout = layout;
  
//设置左边成员布局
NERtcLiveStreamUserTranscoding *user1 = [[NERtcLiveStreamUserTranscoding alloc] init];
user1.uid = 66601;
user1.audioPush = true;        
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.x = 0; 
    user1.y = 0; 
    user1.width = 360; 
    user1.height = 640; 
    user1.adaption = kNERtcLsModeVideoScaleCropFill;
    user1.zOrder = 1;
    }
    
//设置右边成员布局
NERtcLiveStreamUserTranscoding *user2 = [[NERtcLiveStreamUserTranscoding alloc]init];
user2.uid = 66602;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
    user2.x = 360;
    user2.y = 0;
    user2.width = 360;
    user2.height = 640;
    user2.adaption = kNERtcLsModeVideoScaleCropFill;
    user2.zOrder = 1;
}
layout.users = @[user1,user2];

//设置音视频流编码参数
NERtcLiveConfig *config = [[NERtcLiveConfig alloc] init];
config.interruptedPlaceImage = true;
config.singleVideoPassthrough = true;
config.audioBitrate = 64 kbps;
config.sampleRate = kNERtcLiveStreamAudioSampleRate48000;
config.audioCodecProfile= kNERtcLiveStreamAudioCodecProfileLCAAC;
config.channels = 2;
layout.config = config;

//设置占位图片布局
NERtcLiveStreamImageInfo *image1 = [[NERtcLiveStreamImageInfo alloc] init];
image1.url = www.163.com/test.jpg; 
image1.x = 360; 
image1.y = 0; 
image1.width = 360; 
image1.height = 640;
image.zOrder = 0; 
layout.bgImages = @[image1];
    
//调用 addLiveStreamTask 接口添加推流任务
int ret = [[NERtcEngine sharedEngine] addLiveStreamTask:info
                                            compeltion:^(NSString * _Nonnull taskId, kNERtcLiveStreamError errorCode) {

    NSString *toast = !errorCode ? @"添加成功" : [NSString stringWithFormat:@"添加失败 errorcode = %d",errorCode];
    MakeToast(toast);
}];

if (ret != 0) {
    MakeToast(@"调用添加推流任务失败");
}

效果展示

  • 原始画布:

    原始画布

  • 增加占位图片:

    增加占位图片

  • 正常显示画面:

    正常显示画面

  • 右侧用户断线:

    右侧用户断线

  • 左侧用户断线:

    左侧用户断线

常用布局设置

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

双人横向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout *layout = [[NERtcLiveStreamLayout alloc] init];
layout.width = 640;     
layout.height = 360;  
layout.backgroundColor = #16777215;
info.layout = layout;
  
//设置左边成员布局
NERtcLiveStreamUserTranscoding *user1 = [[NERtcLiveStreamUserTranscoding alloc] init];
user1.uid = 66601;
user1.audioPush = true;        
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.x = 0; 
    user1.y = 0; 
    user1.width = 320; 
    user1.height = 360; 
    user1.adaption = kNERtcLsModeVideoScaleCropFill;
    user1.zOrder = 1;
    }
    
//设置右边成员布局
NERtcLiveStreamUserTranscoding *user2 = [[NERtcLiveStreamUserTranscoding alloc]init];
user2.uid = 66602;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
    user2.x = 320;
    user2.y = 0;
    user2.width = 320;
    user2.height = 360;
    user2.adaption = kNERtcLsModeVideoScaleCropFill;
    user2.zOrder = 1;
}
layout.users = @[user1,user2];

三人纵向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout *layout = [[NERtcLiveStreamLayout alloc] init];
layout.width = 360;     
layout.height = 640;  
layout.backgroundColor = #16777215;
info.layout = layout;
  
//设置上方成员布局
NERtcLiveStreamUserTranscoding *user1 = [[NERtcLiveStreamUserTranscoding alloc] init];
user1.uid = 123;
user1.audioPush = true;        
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.x = 0; 
    user1.y = 0; 
    user1.width = 360; 
    user1.height = 320; 
    user1.adaption = kNERtcLsModeVideoScaleCropFill;
    user1.zOrder = 1;
    }
    
//设置左下成员布局
NERtcLiveStreamUserTranscoding *user2 = [[NERtcLiveStreamUserTranscoding alloc]init];
user2.uid = 456;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
    user2.x = 0;
    user2.y = 320;
    user2.width = 180;
    user2.height = 320;
    user2.adaption = kNERtcLsModeVideoScaleCropFill;
    user2.zOrder = 1;
}

//设置右下成员布局
NERtcLiveStreamUserTranscoding *user3 = [[NERtcLiveStreamUserTranscoding alloc]init];
user3.uid = 789;
user3.audioPush = true;
user3.videoPush = enableVideo;
if (user3.videoPush) {
    user3.x = 180;
    user3.y = 320;
    user3.width = 180;
    user3.height = 320;
    user3.adaption = kNERtcLsModeVideoScaleCropFill;
    user3.zOrder = 1;
}
layout.users = @[user1,user2,user3];

1 + N 悬浮布局

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
NERtcLiveStreamLayout *layout = [[NERtcLiveStreamLayout alloc] init];
layout.width = 360;     
layout.height = 640;  
layout.backgroundColor = #16777215;
info.layout = layout;
  
//设置上方成员布局
NERtcLiveStreamUserTranscoding *user1 = [[NERtcLiveStreamUserTranscoding alloc] init];
user1.uid = 123;
user1.audioPush = true;        
user1.videoPush = enableVideo;
if (user1.videoPush) {
    user1.x = 0; 
    user1.y = 0; 
    user1.width = 360; 
    user1.height = 640; 
    user1.adaption = kNERtcLsModeVideoScaleCropFill;
    user1.zOrder = 1;
    }
    
//设置左下成员布局
NERtcLiveStreamUserTranscoding *user2 = [[NERtcLiveStreamUserTranscoding alloc]init];
user2.uid = 456;
user2.audioPush = true;
user2.videoPush = enableVideo;
if (user2.videoPush) {
    user2.x = 45;
    user2.y = 390;
    user2.width = 110;
    user2.height = 213;
    user2.adaption = kNERtcLsModeVideoScaleCropFill;
    user2.zOrder = 1;
}

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