Tutorial: 云端混流与转推CDN

云端混流与转推CDN

功能描述

本文主要描述如何使用 CDNStreaming 插件,实现云端混流、转推 CDN、回推混流到 TRTC 房间的功能。

前提条件

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

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

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

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

使用步骤

一、注册插件

在使用之前,首先需要注册插件。以下是注册插件的示例代码:

import TRTC from 'trtc-sdk-v5';
import { CDNStreaming, PublishMode } from 'trtc-sdk-v5/plugins/cdn-streaming';
const trtc = TRTC.create({ plugins: [CDNStreaming] });

二、使用插件

本插件提供了四种推流转码模式

模式 A:转推摄像头麦克风流

const options = {
  target: {
    publishMode: PublishMode.PublishMainStreamToCDN,
    // ... 其他参数
  }
}

模式 B:转推屏幕分享流

const options = {
  target: {
    publishMode: PublishMode.PublishSubStreamToCDN,
    // ... 其他参数
  }
}

模式 C:转推混流

const options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToCDN,
    // ... 其他参数
  },
  encoding: {
    // 云端混流后输出的画面编码参数
  },
  mix: {
    // 云端混流的配置参数
  }
}

模式 D:回推混流

const options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToRoom,
    robotUser: {
      userId: 'push_back_xxxx', // 回推到指定房间的机器人,不要跟其他 userId 重复
      roomId: 1234
    }
    // ... 其他参数
  },
  encoding: {
    // 云端混流后输出的画面编码参数
  },
  mix: {
    // 云端混流的配置参数
  }
}

对于每一种模式,均满足以下生命周期

  • 调用 1 次startPlugin 方法启动插件 trtc.startPlugin('CDNStreaming', options);
  • 调用 0 或 N 次 updatePlugin 方法更新参数 trtc.updatePlugin('CDNStreaming', options);
  • 调用 1 次 stopPlugin 方法停止插件 trtc.stopPlugin('CDNStreaming', options);

详细的 options 参数可见 参数定义

三、使用示例

接下来将以三个使用场景为例,介绍插件的使用。

  • 场景 1:实现将摄像头、屏幕分享推流到腾讯云 CDN
  • 场景 2:将混流转推到腾讯云 CDN
  • 场景 3:推流到指定 CDN

场景 1:实现将摄像头、屏幕分享推流到腾讯云 CDN

步骤(1):选择【旁路推流方式】,见本文前提条件第 3 条

  • 若您选择“全局自动旁路”模式

    TRTC 房间里的摄像头流、屏幕分享流将自动被推流到腾讯云 CDN,每一路画面都自动配备一路对应的播放地址,该地址的格式如下:

    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)}

    此时已完成自动推流,通过默认地址播放可以播放。若想修改播放地址,可以继续阅读步骤(2)。

  • 若您选择“手动旁路”模式

    TRTC 房间里的流不会被自动被推流到腾讯云 CDN,请阅读步骤(2)手动开启推流。

步骤(2):设定插件参数

选择想要转推摄像头流还是屏幕分享流

  • 若转推摄像头流,则参数的 options.target.publishMode 填写 PublishMode.PublishMainStreamToCDN
  • 若转推屏幕分享流,则参数的 options.target.publishMode 填写 PublishMode.PublishSubStreamToCDN

选择是否要自定义播放地址

  • 若要指定推流后播放地址,则需要设置参数的 options.target.streamId

代码示例如下:

// 开启插件
const options = {
  target: {
    publishMode: PublishMode.PublishMainStreamToCDN
  }
}
try {
  await trtc.startPlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming start failed', error);
}

摄像头流开始被转推到 CDN,使用的是播放地址:http://[播放域名]/live/${sdkAppId}_${roomId}_${userId}_main.flv

若要修改播放地址,可以修改 streamId 字段

// 更新转推参数
const options = {
  target: {
    publishMode: PublishMode.PublishMainStreamToCDN,
    streamId: 'stream001'
  }
}
try {
  await trtc.updatePlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming update failed', error);
}

播放地址变更为:http://[播放域名]/live/stream001.flv

不需要进行转推时停止插件

// 停止插件,只需要填写 publishMode 字段
const options = {
  target: {
    publishMode: PublishMode.PublishMainStreamToCDN,
  }
}
try {
  await trtc.stopPlugin('CDNStreaming', options);
} catch (error) {
  console.log('CDNStreaming stop failed', error);
}

可通过 流管理界面 查看目前的流状态。

场景二:将混流转推到腾讯云 CDN

接下里主要介绍 Web 端 SDK 发起云端混流。其他端实现方式可参考 云端混流转码

当发起混流转码时,本插件会向腾讯云的转码服务器发送一条指令,目的是将房间里的多路音视频流混合为一路。开发者可以通过 encodingmix 参数来调整每一路混入流的参数和混合后音视频流的编码值,原理图如下:

您可以在开启插件时对本地用户流和远端用户流进行任意排版,并且在远端流开始推流和停止推流的时候根据需求及时调整混流参数。可实现的其中一种效果如下:

  1. 调用 startPlugin,混流的布局如图 A 所示;
  2. 想要新增屏幕分享时,调用 updatePlugin 更新参数,混流的布局如图 B 所示;
  3. 不需要混流时调用 stopPlugin。

以实现上面的效果为例,开启的步骤为:

  1. 将插件参数 target.publishMode 设置为 PublishMode.PublishMixStreamToCDN,表示目前是对混流进行操作。

  2. 指定 encoding 参数中的 videoWidth,videoHeight, videoBitrate, videoFramerate, videoGOP, audioSampleRate, audioBitrate, audioChannels 这些关乎混流输出流的音视频质量的参数,同时您也可以通过指定 mix 参数中的 backgroundColor 及 backgroundImage 参数指定混流输出流的背景颜色和背景图片。

    背景图需要您事先在 “实时音视频控制台 > 应用管理 > 功能配置 > 素材管理” 中单击【新增图片】按钮进行上传。 上传成功后可以获得对应的“图片ID”,然后将“图片ID”转换成字符串类型并设置到 backgroundImage 里即可。 例如:假设“图片ID”为 63,则设置 backgroundImage 为 "63";

  3. 组装 mix.audioMixUserList 参数,将需要用户的音频填入到数组中。

  4. 组装 mix.videoLayoutList 参数,如果需要视频布局信息,则可以将不同的布局信息填写到这里的数组中。

  5. 配置好参数后,开启混流,将会自动发布在 CDN 上,默认播放地址为 http://播放域名/live/${sdkAppId}_${roomId}_${userId}_main.flv,若配置了 streamId,则变为 http://播放域名/live/[streamId].flv

// 开启混流
let options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToCDN,
    streamId: 'mix-stream',
  },
  encoding: {
    videoWidth: 1280,
    videoHeight: 720,
    videoBitrate: 1500,
    videoFramerate: 15,
  },
  mix: {
    audioMixUserList: [
      {
        userId: 'current_user_id', // 当前用户 ID
      }
    ],
    videoLayoutList: [
      {
        fixedVideoUser: {
          userId: 'current_user_id', // 当前用户 ID
        },
        width: 640,
        height: 480,
        locationX: 0,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN, // 这个用户的摄像头流还是屏幕分享流
        zOrder: 1
      },
    ]
  }
};
try {
  await trtc.startPlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming start failed', error);
}
// 更新混流参数,此处为添加上当前用户的屏幕分享
let options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToCDN,
    streamId: 'mix-stream',
  },
  encoding: {
    videoWidth: 1280,
    videoHeight: 720,
    videoBitrate: 1500,
    videoFramerate: 15,
  },
  mix: {
    audioMixUserList: [
      {
        userId: 'current_user_id',
      }
    ],
    videoLayoutList: [
      {
        fixedVideoUser: {
          userId: 'current_user_id',
        },
        width: 640,
        height: 480,
        locationX: 0,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
        zOrder: 1
      },
      {
        fixedVideoUser: {
          userId: 'current_user_id',
        },
        width: 640,
        height: 480,
        locationX: 640,
        locationY: 0,
        fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_SUB,
        zOrder: 1
      },
    ]
  }
}
try {
  await trtc.updatePlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming update failed', error);
}
// 停止混流
let options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToCDN,
  }
}
try {
  await trtc.updatePlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming update failed', error);
}

场景三:推流到指定 CDN

  1. 在任意云服务商获取 CDN 推流地址 url。

  2. 实时音视频控制台【应用管理-配置-旁路转推配置】查看默认推流域名的前6个数字是 bizid,应用的 SDKAppId 是 appid。

  3. 开始向指定 CDN 地址发布当前用户的音视频流。以发布用户摄像头流到指定 CDN 为例

    let options = {
      target: {
        publishMode: PublishMode.PublishMainStreamToCDN,
        appId: 0,
        bizId: 0,
        url: ''
      }
    };
    try {
      await trtc.startPlugin('CDNStreaming', options);
    } catch (error) {
      console.error('CDNStreaming start customCDN failed', error);
    }
    

    停止发布的代码:

    let options = {
      target: {
        publishMode: PublishMode.PublishMainStreamToCDN,
      }
    }
    try {
      await trtc.stopPlugin('CDNStreaming', options);
    } catch (error) {
      console.error('CDNStreaming stop customCDN failed ', error);
    }
    

场景四:回推混流到指定 trtc 房间

支持以机器人的形式进入指定房间,在房间内发布混流音视频。

注意:

  • 此功能会自动在当前房间进入一个 userId 为 mcu_robot_${roomId}_${userId} 的拉流机器人,房间内其他 userId 要避免相同导致互踢
  • 此功能混流会有转码费用
  • audioMixUserList 为空时,默认混所有人,若不需要混流,可传入不存在的 userId,如有疑问请联系客服人员
// 3333 房间的用户 user_123 发起该任务,实现在 4444 房间中用 push_back_user_321 机器人发布混流
let options = {
    target: {
      publishMode: PublishMode.PublishMixStreamToRoom,
      robotUser: {
        userId: `push_back_user_321`, // 建议动态生成
        roomId: 4444,
      }
    },
    encoding: {
      videoWidth: 1280,
      videoHeight: 720,
      videoBitrate: 1500,
      videoFramerate: 15,
    },
    mix: {
      audioMixUserList: [
        {
          userId: 'user_123',
          roomId: 3333
        }
      ],
      videoLayoutList: [
        {
          fixedVideoUser: {
            userId: 'user_123',
            roomId: 3333
          },
          width: 640,
          height: 480,
          locationX: 0,
          locationY: 0,
          fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
          zOrder: 1
        },
        {
          fixedVideoUser: {
            userId: 'user_123',
            roomId: 3333
          },
          width: 640,
          height: 480,
          locationX: 640,
          locationY: 0,
          fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_SUB,
          zOrder: 1
        },
      ]
    }
  };
try {
  await trtc.startPlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming start push stream to room failed', error);
}

更新视频布局

let options = {
    target: {
      publishMode: PublishMode.PublishMixStreamToRoom
    },
    mix: {
      videoLayoutList: [
        {
          fixedVideoUser: {
            userId: 'user_123',
            roomId: 3333
          },
          width: 640,
          height: 480,
          locationX: 640,
          locationY: 0,
          fixedVideoStreamType: TRTC.TYPE.STREAM_TYPE_MAIN,
          zOrder: 1
        }
      ]
    }
  };
try {
  await trtc.updatePlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming update push stream to room failed', error);
}

停止发布的代码:

let options = {
  target: {
    publishMode: PublishMode.PublishMixStreamToRoom,
  }
}
try {
  await trtc.stopPlugin('CDNStreaming', options);
} catch (error) {
  console.error('CDNStreaming stop push stream to room failed ', error);
}

API 说明

对于 startPlugin('CDNStreaming', options)updatePlugin('CDNStreaming', options),参数类型可见 CDNStreamingOptions

对于 stopPlugin('CDNStreaming', options),参数只需要填入 options.target.publishMode 字段即可。

注意事项

  1. 录制混合后的音频流,请参考 云端录制

  2. 云端混流转码需要对输入 MCU 集群的音视频流进行解码后重新编码输出,将产生额外的服务成本,因此 TRTC 将向使用 MCU 集群进行云端混流转码的用户收取额外的增值费用。云端混流转码费用根据转码输出的分辨率大小转码时长进行计费,转码输出的分辨率越高、转码输出的时间越长,费用越高。详情请参见 云端混流转码计费说明

  3. 音视频时长计费说明,参考 计费说明

  4. 退出房间后不会继续计费,但在重新进房时会自动继续开启,若想直接终止转推 CDN 和混流,请执行 stopPlugin 对应的 publishMode。

常见问题

Q.无法停止推流?

请检查是否在控制台开启了“全局自动旁路”,该模式下无法通过接口停止。

Q.如何查看目前所有的流?

可通过 流管理界面 查看目前的流状态。

Q.屏幕分享模糊?

SDK 默认使用 1080p 参数配置来采集屏幕分享,具体参考接口:startScreenShare