旁路推流画面布局

更新时间: 2023/01/17 09:03:13

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

限制说明

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

设置画面布局

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

背景画布

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

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

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

background_color

int

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

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

用户画面

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

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

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

z_order

int

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

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

adaption

int

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

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

audio_push

bool

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

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

video_push

bool

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

占位图片

通过 NERtcLiveStreamLayout 类的 bg_image_countbg_image参数设置占位图个数、每张占位图对应的画面属性。

  • 支持设置最多 6 张图片。
  • 您可以通过 NERtcLiveConfiginterrupted_place_image 字段选择是否开启此功能;若设置为关闭,则此设置无效。

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

参数名称 类型 描述
url char 占位图片的 URL。
x int 通过 x 和 y 指定画布坐标中的一个点,该点将作为占位图片的左上角。
x 参数用于设置画布的横轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
y int 通过 x 和 y 指定画布坐标中的一个点,该点将作为占位图片的左上角。
y 参数用于设置画布的纵轴坐标值。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
width int 该占位图片在画布中的宽度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。
height int 该占位图片在画布中的高度。
取值范围为 0 ~ 1920,若设置为奇数值,会自动向下取偶。

z_order

int

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

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

布局示例

本文档以服务端 API 创建推流任务为例,为您展示通过服务端 API 接口 layout 参数设置旁路推流画面布局的方式。

请求示例

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

示例代码如下:

C++//加入房间前设置直播模式
NERtcChannelProfileType channelProfileType = kNERtcChannelProfileLiveBroadcasting;
rtc_engine_->setChannelProfile(channelProfileType);

//加入房间后创建推流任务
//添加推流任务的异步callback,更多错误码请参考onAddLiveStreamTask的API文档
void onAddLiveStreamTask(const char* task_id, const char* url, int error_code){
    if (code == kNERtcNoError) {
        showToast("添加推流任务成功 : taskId " + taskId);
    } else {
        showToast("添加推流任务失败 : taskId " + taskId + " , code : " + code);
    }
};

//推流任务数据结构
NERtcLiveStreamTaskInfo ls_task_info_;
strncpy(ls_task_info_.task_id, task_id.c_str(), kNERtcMaxTaskIDLength);
strncpy(ls_task_info_.stream_url, url.c_str(), kNERtcMaxURILength);
ls_task_info_.ls_mode = kNERtcLsModeVideo;
ls_task_info_.server_record_enabled = false;

//设置音视频编码参数
ls_task_info_.config.interrupted_place_image = true;
ls_task_info_.config.single_video_passthrough = true;
ls_task_info_.config.audio_bitrate = 64;
ls_task_info_.config.sampleRate = kNERtcLiveStreamAudioSampleRate48000;
ls_task_info_.config.audioCodecProfile = NERtcLiveStreamAudioCodecProfileLCAAC;
ls_task_info_.config.channels = 2;

//设置整体布局
ls_task_info_.layout.background_color = 0x808080; 
ls_task_info_.layout.width = 720;
ls_task_info_.layout.height = 640;

//设置直播成员布局
ls_task_info_.layout.user_count = 2;
ls_task_info_.layout.users = new NERtcLiveStreamUserTranscoding[2];
ls_task_info_.layout.users[0].uid = 66601;
ls_task_info_.layout.users[1].uid = 66602;
for (int i = 0; i < ls_task_info_.layout.user_count; i++)
{
    ls_task_info_.layout.users[i].adaption = kNERtcLsModeVideoScaleFit;
    ls_task_info_.layout.users[i].video_push = true;
    ls_task_info_.layout.users[i].x = 360 * i;     
    ls_task_info_.layout.users[i].y = 0;         
    ls_task_info_.layout.users[i].width = 360;     
    ls_task_info_.layout.users[i].height = 640;    
    ls_task_info_.layout.users[i].audio_push = true;
    ls_task_info_.layout.users[i].zorder = 1;
}

//设置占位图布局
ls_task_info_.layout.bg_image_count = 1;
ls_task_info_.layout.bg_image       = new NERtcLiveStreamImageInfo;
std::string url                     = "www.163.com/test.jpg";
memset(ls_task_info_.layout.bg_image, 0, sizeof(NERtcLiveStreamImageInfo));
memcpy(ls_task_info_.layout.bg_image.url, url.data(), url.size());
ls_task_info_.layout.bg_image->x      =360;
ls_task_info_.layout.bg_image->y      = 0;
ls_task_info_.layout.bg_image->width  = 360;
ls_task_info_.layout.bg_image->height = 640;
ls_task_info_.layout.bg_image->zorder = 0;

// 之后用户以配置了的uid进入房间,开启推流开关即可推流
int ret = addLiveStreamTask(ls_task_info_);
if (ret != 0) {
    showToast("调用添加推流任务失败 , ret : " + ret);
}

效果展示

  • 原始画布:

    原始画布

  • 增加占位图片:

    增加占位图片

  • 正常显示画面:

    正常显示画面

  • 右侧用户断线:

    右侧用户断线

  • 左侧用户断线:

    左侧用户断线

常用布局设置

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

双人横向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
ls_task_info_.layout.background_color = 0x808080; 
ls_task_info_.layout.width = 640;
ls_task_info_.layout.height = 360;

//设置直播成员布局
ls_task_info_.layout.user_count = 2;
ls_task_info_.layout.users = new NERtcLiveStreamUserTranscoding[2];
ls_task_info_.layout.users[0].uid = 66601;
ls_task_info_.layout.users[1].uid = 66602;
for (int i = 0; i < ls_task_info_.layout.user_count; i++)
{
    ls_task_info_.layout.users[i].adaption = kNERtcLsModeVideoScaleFit;
    ls_task_info_.layout.users[i].video_push = true;
    ls_task_info_.layout.users[i].x = 320 * i;     
    ls_task_info_.layout.users[i].y = 0;         
    ls_task_info_.layout.users[i].width = 320;     
    ls_task_info_.layout.users[i].height = 360;    
    ls_task_info_.layout.users[i].audio_push = true;
    ls_task_info_.layout.users[i].zorder = 1;
}

三人纵向平铺

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
ls_task_info_.layout.background_color = 0x808080; 
ls_task_info_.layout.width = 360;
ls_task_info_.layout.height = 640;

//设置直播成员布局
ls_task_info_.layout.user_count = 3;
ls_task_info_.layout.users = new NERtcLiveStreamUserTranscoding[3];

//设置上方成员布局
ls_task_info_.layout.users[0].uid        = 123;
ls_task_info_.layout.users[0].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[0].video_push = true;
ls_task_info_.layout.users[0].x          = 0;     
ls_task_info_.layout.users[0].y          = 0;         
ls_task_info_.layout.users[0].width      = 360;     
ls_task_info_.layout.users[0].height     = 320;    
ls_task_info_.layout.users[0].audio_push = true;
ls_task_info_.layout.users[0].zorder     = 1;

//设置左下角成员布局
ls_task_info_.layout.users[1].uid        = 456;
ls_task_info_.layout.users[1].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[1].video_push = true;
ls_task_info_.layout.users[1].x          = 0;     
ls_task_info_.layout.users[1].y          = 320;         
ls_task_info_.layout.users[1].width      = 180;     
ls_task_info_.layout.users[1].height     = 320;    
ls_task_info_.layout.users[1].audio_push = true;
ls_task_info_.layout.users[1].zorder     = 1;

//设置右下角成员布局
ls_task_info_.layout.users[2].uid        = 789;
ls_task_info_.layout.users[2].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[2].video_push = true;
ls_task_info_.layout.users[2].x          = 180;     
ls_task_info_.layout.users[2].y          = 320;         
ls_task_info_.layout.users[2].width      = 180;     
ls_task_info_.layout.users[2].height     = 320;    
ls_task_info_.layout.users[2].audio_push = true;
ls_task_info_.layout.users[2].zorder     = 1;

1 + N 悬浮布局

  • 显示效果

    image

  • layout 参数配置示例

//设置整体布局
ls_task_info_.layout.background_color = 0x808080; 
ls_task_info_.layout.width = 360;
ls_task_info_.layout.height = 640;

//设置直播成员布局
ls_task_info_.layout.user_count = 3;
ls_task_info_.layout.users = new NERtcLiveStreamUserTranscoding[3];

//设置上方成员布局
ls_task_info_.layout.users[0].uid        = 123;
ls_task_info_.layout.users[0].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[0].video_push = true;
ls_task_info_.layout.users[0].x          = 0;     
ls_task_info_.layout.users[0].y          = 0;         
ls_task_info_.layout.users[0].width      = 360;     
ls_task_info_.layout.users[0].height     = 640;    
ls_task_info_.layout.users[0].audio_push = true;
ls_task_info_.layout.users[0].zorder     = 1;

//设置左下角成员布局
ls_task_info_.layout.users[1].uid        = 456;
ls_task_info_.layout.users[1].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[1].video_push = true;
ls_task_info_.layout.users[1].x          = 45;     
ls_task_info_.layout.users[1].y          = 390;         
ls_task_info_.layout.users[1].width      = 110;     
ls_task_info_.layout.users[1].height     = 213;    
ls_task_info_.layout.users[1].audio_push = true;
ls_task_info_.layout.users[1].zorder     = 1;

//设置右下角成员布局
ls_task_info_.layout.users[2].uid        = 789;
ls_task_info_.layout.users[2].adaption   = kNERtcLsModeVideoScaleFit;
ls_task_info_.layout.users[2].video_push = true;
ls_task_info_.layout.users[2].x          = 185;     
ls_task_info_.layout.users[2].y          = 390;         
ls_task_info_.layout.users[2].width      = 110;     
ls_task_info_.layout.users[2].height     = 213;    
ls_task_info_.layout.users[2].audio_push = true;
ls_task_info_.layout.users[2].zorder     = 1;
此文档是否对你有帮助?
有帮助
去反馈
  • 限制说明
  • 设置画面布局
  • 背景画布
  • 用户画面
  • 占位图片
  • 布局示例
  • 请求示例
  • 效果展示
  • 常用布局设置
  • 双人横向平铺
  • 三人纵向平铺
  • 1 + N 悬浮布局