Tutorial: 实现跨房连麦

实现跨房连麦

功能描述

在直播场景中,常常需要跨房连麦来支持不同直播间的主播实时互动的需求,本文主要介绍 Web 端跨房间连麦及混流后推流到 CDN 的实现方式。

前提条件

在实现 Web 端跨房连麦之前,我们先来确认一下实时音视频的一些基础信息。

  • userId,用户的标识 Id, 每个用户拥有独一无二的 Id;
  • roomId,数字类型房间 Id;
  • strRoomId,字符串类型房间 Id;

注意:混流双方的房间类型需要相同,不可以混用。

  • trtc,由 TRTC.create 创建的客户端对象,拥有加入通话房间,发布本地音视频流,订阅远端流的功能;

实现基础音视频通话时,我们根据 trtc 进入某个特定的 roomId 房间并发布本地流、订阅远端流以实现同一个房间中多个用户之间的音视频通话。

在 Web 端, 让不同房间的 A,B 两个主播,分别使用自己的 userId 创建新的 trtc,进入到对方主播所在的房间订阅对方主播的流,即可实现跨房连麦。

使用步骤

步骤一:主播进入各自的房间并发布流

主播 A(创建 trtcA1)以主播身份在 1000 房间推流;

主播 B(创建 trtcB1)以主播身份在 2000 房间推流。

// 主播 A 在 1000 房间推流
const trtcA1 = TRTC.create({ plugins: [CDNStreaming] });
await trtcA1.enterRoom({
  sdkAppId: 0,
  userId: 'A',
  userSig: 'xxxx',
  scene: TRTC.TYPE.SCENE_LIVE,
  roomId: 1000,
  role: TRTC.TYPE.ROLE_ANCHOR
})
trtcA1.startLocalVideo()
trtcA1.startLocalAudio()
// 主播 B 在 2000 房间推流
const trtcB1 = TRTC.create({ plugins: [CDNStreaming] });
await trtcB1.enterRoom({
  sdkAppId: 0,
  userId: 'B',
  userSig: 'xxxx',
  scene: TRTC.TYPE.SCENE_LIVE,
  roomId: 2000,
  role: TRTC.TYPE.ROLE_ANCHOR
})
trtcB1.startLocalVideo()
trtcB1.startLocalAudio()

此时,1000 房间和 2000 房间的用户状态如下:

               房间 1000                   房间 2000
              -------------              ------------
 跨房连麦前:  | 主播 A      |             | 主播 B     |
             | 观众 U V W  |             | 观众 X Y Z |
              -------------              ------------

对于观众是通过标准直播拉流(CDN拉流)的情况,主播需要将自己的音视频流推流到 CDN,请参考 实现推流到 CDN

步骤二:主播跨房连麦

主播 A(创建 trtcA2)以观众身份进入房间 2000 订阅主播 B 的流;

主播 B(创建 trtcB2)以观众身份进入房间 1000 订阅主播 A 的流;

此时主播 A 和 主播 B 跨房间连麦成功。

// 主播 A 以观众身份进入 2000 房间并订阅主播 B 的流
const trtcA2 = TRTC.create()
trtcA2.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
  if (event.userId === 'B') {
    trtcA2.startRemoteVideo({
      view: 'B_containerId',
      userId: event.userId,
      streamType: event.streamType
    });
  }
})
await trtcA2.enterRoom({
  sdkAppId: 0,
  userId: 'A',
  userSig: 'xxxx',
  scene: TRTC.TYPE.SCENE_LIVE,
  roomId: 2000,
  role: TRTC.TYPE.ROLE_AUDIENCE
})
// 主播 B 以观众身份进入 1000 房间并订阅主播 A 的流
const trtcB2 = TRTC.create()
trtcB2.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
  if (event.userId === 'A') {
    trtcB2.startRemoteVideo({
      view: 'A_containerId',
      userId: event.userId,
      streamType: event.streamType
    });
  }
})
await trtcB2.enterRoom({
  sdkAppId: 0,
  userId: 'B',
  userSig: 'xxxx',
  scene: TRTC.TYPE.SCENE_LIVE,
  roomId: 1000,
  role: TRTC.TYPE.ROLE_AUDIENCE
})
                 房间 1000                    房间 2000
              --------------               --------------
 跨房连麦后:  | 主播 A        |             | 主播 B       |
             | 观众 B U V W  |             | 观众 A X Y Z |
              --------------               --------------

步骤三:跨房连麦后混流

对于标准直播拉流(CDN拉流)的场景来说,主播跨房间连麦之后需要将双方主播连麦的音视频混流后发布到 CDN。

a. 混流前提条件 - 开通旁路

  1. TRTC SDK 版本需要 >= 5.1。

  2. 开通腾讯 云直播 服务。应国家相关部门的要求,直播播放必须配置播放域名,具体操作请参考 域名管理

  3. 实时音视频控制台 左侧导航栏选择【应用管理】,单击目标应用所在行的【配置】,打开【启用旁路推流】的开关。

    • “全局自动旁路”模式下,TRTC 所有上行音视频流都会被自动转推到腾讯云 CDN。
    • “指定流旁路”模式下,您可以通过该插件或者 服务端 REST API 将指定音视频流推送到 CDN 且指定播放地址。

b. 发起混流

连麦中的主播需要在各自的推流房间中发起混流,将其他房间主播的流混到自己已经发布在 CDN 的音视频流上。

// 主播 A 发起跨房间混流,将房间 2000 中 B 主播的音视频流混到自己的旁路流
// 注意:必须由发布本地流的 trtcA1 发起混流
trtcA1.startPlugin('CDNStreaming', {
  target: {
    publishMode: CDNStreaming.TYPE.PublishMode.PublishMixStreamToCDN,
  },
  encoding: {
    videoWidth: 1280,
    videoHeight: 480,
    videoBitrate: 1500,
    videoFramerate: 15
  },
  mix: {
    audioMixUserList: [
      {
        userId: 'A',
        roomId: 1000
      },
      {
        userId: 'B',
        roomId: 2000
      }
    ],
    videoLayoutList: [
      {
        fixedVideoUser: {
          userId: 'A',
          roomId: 1000
        },
        width: 640,
        height: 480,
        locationX: 0,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
        zOrder: 1
      },
      {
        fixedVideoUser: {
          userId: 'B',
          roomId: 2000,
        },
        width: 640,
        height: 480,
        locationX: 640,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
        zOrder: 1
      },
    ]
  }
})
// 主播 B 发起跨房间混流,将房间 1000 中 A 主播的音视频流混到自己的旁路流
// 注意:必须由发布本地流的 trtcB1 发起混流
trtcB1.startPlugin('CDNStreaming', {
  target: {
    publishMode: CDNStreaming.TYPE.PublishMode.PublishMixStreamToCDN,,
  },
  encoding: {
    videoWidth: 1280,
    videoHeight: 480,
    videoBitrate: 1500,
    videoFramerate: 15
  },
  mix: {
    audioMixUserList: [
      {
        userId: 'A',
        roomId: 1000
      },
      {
        userId: 'B',
        roomId: 2000
      }
    ],
    videoLayoutList: [
      {
        fixedVideoUser: {
          userId: 'B',
          roomId: 1000
        },
        width: 640,
        height: 480,
        locationX: 0,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
        zOrder: 1
      },
      {
        fixedVideoUser: {
          userId: 'A',
          roomId: 2000,
        },
        width: 640,
        height: 480,
        locationX: 640,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
        zOrder: 1
      },
    ]
  }
})

c. CDN 拉流

情况一:当您推流到腾讯云 CDN 之后,TRTC 房间里的每一路画面都匹配一路对应的播放地址,播放地址拼接格式如下:

http://播放域名/live/[streamId].flv
  • [播放域名] 为云直播中配置的播放域名,查看已有的域名请参考 域名管理
  • 摄像头流的 [streamId] 默认值为 ${sdkAppId}_${roomId}_${userId}_main
  • 屏幕分享流的 [streamId] 默认值为${sdkAppId}_${roomId}_${userId}_aux
  • 当 roomId 或者 userId 包含特殊字符时(除了大小写英文字母(a-zA-Z)、数字(0-9)、连字符及下划线之外的均为特殊字符),默认 streamId 摄像头流为 ${sdkAppId}_${md5(${roomId}_${userId}_main)},屏幕分享流为 ${sdkAppId}_${md5(${roomId}_${userId}_aux)}

情况二:当您推流到指定 CDN 地址之后,请使用您的推流地址对应的拉流地址观看混合之后的流;

如需详细配置,可参考 云端混流与转推CDN教程 - 使用步骤