多主播场景下的视频体验优化

  • Android

更新时间不可用

了解实时互动 RTC 在不同平台上的多主播场景下的视频体验优化方式,包括接入流程、关键配置和平台差异。

在多主播(4 个或以上)发流的视频场景下,观众端面临着如下挑战和需求:

  • 设备性能和下行带宽压力:多路视频流订阅对设备性能和观众端带宽的要求较高,尤其在中低端设备上可能出现卡顿和掉帧问题,容易给观众带来负面体验。
  • 灵活布局需求:需要提供自定义视频画面布局的功能,支持观众调整每个主播画面的位置,以满足观众个性化的观看需求。
  • 窗口切换与放大需求:在众多主播中,属于每个主播的画面大小有限,灵活切换和调整窗口大小可以实现“千人千面”的观看体验。

该方案可广泛应用于如下场景:

  • 团战 PK
  • 多人会议
  • 在线教育大班课

技术原理

客户端自定义合图布局需要结合云端转码服务一起使用,技术原理如下所示:

当观众端收到已转码的合图视频流后,在本地实现自定义合图布局的技术原理如下所示:

前提条件

  • 项目已集成 RTC SDK v4.5.x 以上版本。

  • 已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。

  • 已实现云端转码,将合图后的视频转发至其他频道,并在调用创建云端转码 API 时设置以下参数:

    JSON
    "outputs": [
      {   
          "seiOption":{
              "source":{
                  "agora": {
                      "uidvideoLayout": true
                  }
              },
              "sink":{
                  "type": 100
              }
          }
      }
    ]
    

实现方法

本节介绍如何实现客户端自定义合图布局,API 调用时序如下图所示。

通过以下步骤,在接收端实现自定义合图布局。

信息

本文的 API 和示例代码均以 Android 平台为例。如目标平台为 iOS,请参考 iOS 的 API 文档。

  1. 调用 joinChannel[2/2] 加入合图流所在的频道。

  2. 通过 SDK 触发的 onTranscodedStreamLayoutInfo 回调,获取合图视频流的以下信息:

    • 合图视频流的宽、高,以及发布该视频流的用户 ID。
    • 发布合图子视频流的用户 ID。
    • 合图子视频流在合图画布上的 x 和 y 坐标。
    • 合图子视频流的宽度和高度。
    • 合图子视频流在合图画布上的状态:正常渲染、显示为占位符,或显示为黑色图片。
  3. 接收端调用 setupRemoteVideo 方法设置远端视频流在本地的渲染模式,重点参数设置如下所示:

    • uid:将合图视频流转发至当前频道的用户 ID,即在 onTranscodedStreamLayoutInfo 回调中获取的 uid。
    • view:在本地显示的远端视频视图。你可以通过该参数设置每一路子视频流在本地视图中显示的位置。
    • subviewUid:合图视频流中某一路子视频流所对应的用户 ID。

    信息

    • 当 subviewUid 的值不为 0 时,setupMode 的默认值为 VIEW_SETUP_MODE_REPLACE(增加一个视图)。

      • 如果设置了 subviewUid,则对 rect 的设置将不会生效。

    以下示例代码以多频道场景下调用 setupRemoteVideoEx 为例进行介绍,在非多频道场景下调用 setupRemoteVideo 的方式与之类似。

    Java
    mRtcEngine.joinChannelEx(null, connection, mediaOptions, new IRtcEngineEventHandler() {
     @Override
     public void onTranscodedStreamLayoutInfo(final int uid, final VideoLayoutInfo info) {
         super.onTranscodedStreamLayoutInfo(uid, info);
         runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 int size = info.layoutNumber;
    
                 viewGrids.setChildCount(info.layoutNumber);
                 for (int i = 0; i < size; i++) {
                     if(mUserViews.containsKey(info.layoutList[i].uid)) {
                         continue;
                     }
                     // 设置 view 动态添加
                     TextureView textureView = new TextureView(VideoChatViewActivity.this);
                     textureView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
                     users.add(info.layoutList[i].uid);
                     views.add(textureView);
                     mUserViews.put(info.layoutList[i].uid, textureView);
                     viewGrids.addView(textureView);
                     // 设置 VideoCanvas,除 uid 和 subviewUid 以外的其他参数可根据实际需要设置
                     VideoCanvas canvas = new VideoCanvas(textureView);
                     // 转发合图视频流到当前频道的用户 ID
                     canvas.uid = uid;
                     // 对应某一路合图子视频流的用户 ID
                     canvas.subviewUid = info.layoutList[i].uid;
                     canvas.renderMode = Constants.RENDER_MODE_FIT;
                     mRtcEngine.setupRemoteVideoEx(canvas, connection);
                     // 如果要删除某一路子视频流,则添加以下代码
                     VideoCanvas canvas = new VideoCanvas(textureView); // 此处的 textureview 设置为需要删除的 view
                     canvas.uid = uid;
                     canvas.subviewUid = info.layoutList[i].uid;
                     canvas.setupMode = VideoCanvas.VIEW_SETUP_MODE_REMOVE;
                     mRtcEngine.setupRemoteVideoEx(canvas);
                 }
             }
         });
     }
    });
  4. 当合图视频流的布局信息发生变化时,onTranscodedStreamLayoutInfo 回调会再次触发。接收端可根据每一次回调上报的具体信息,重新调用 setupRemoteVideo 调整本地的视图渲染布局。

    信息

    布局信息变化可能存在以下几种情况:

    • 合图子视频在合图画布上的坐标变化。
    • 合图子视频的宽度或高度变化。
    • 合图子视频流的状态变化。当发布该子视频流的主播退出频道时,该路子视频流的 videoState 参数会从 0(正常) 变为 1(该视频流无视频画面)。你可以在调用 setupRemoteVideo 时,将 subviewUid 设置为该路子视频流的用户 ID、然后将 setupMode 设置为 VIEW_SETUP_MODE_REMOVE(删除视图),即可停止渲染该主播的视频画面。
  5. 监听 onUserOffline 回调,当转发合图流的用户退出频道时,停止在接收端渲染合图流。

注意事项

  • 目前仅支持在移动端实现自定义合图布局功能。
  • 当合图视频流被添加了水印时,水印会随所在的区域被渲染,可能会出现被分割的情况。

参考信息