有奖捉虫:办公协同&微信生态&物联网文档专题 HOT

适用场景

CDN 直播观看云端录制回放 等应用场景中,常需要将 TRTC 房间里的多路音视频流混合成一路,您可以使用腾讯云服务端的 MCU 的混流转码集群完成该项工作。MCU 集群能将多路音视频流进行按需混合,并将最终生成的视频流分发给直播 CDN 和云端录制系统。
云端混流有两种控制方式:
方案一:使用服务端 REST 接口 StartMCUMixTranscode(数字房间号版本 / 字符串房间号版本)和 StopMCUMixTranscode(数字房间号版本 / 字符串房间号版本)进行控制,该接口还可以同时支持启动 CDN 观看和发起旧版云端录制功能
方案二:使用客户端 TRTC SDK 的 setMixTranscodingConfig 接口进行控制,其原理如下图:


注意
方案二支持 iOS、Android、Windows、Mac、Electron、Flutter 和 Web 平台的 SDK,如果您希望在微信小程序上也实现混流功能,请使用方案一。

原理解析

云端混流包含解码、混合和再编码三个过程:
解码:MCU 需要将多路音视频流进行解码,包括视频解码和音频解码。
混合:MCU 需要将多路画面混合在一起,并根据来自 SDK 的混流指令实现具体 的排版方案。同时,MCU 也需要将解码后的多路音频信号进行混音处理。
编码:MCU 需要将混合后的画面和声音进行二次编码,并封装成一路音视频流,交给下游系统(例如直播和录制)。




方案一:服务端 REST API 混流方案

启动混流

由您的服务器调用 REST API StartMCUMixTranscode 可以启动云端混流,对于此 API 您需关注如下细节:

步骤1:设置画面排版模式(必需)

通过 StartMCUMixTranscode 中的 LayoutParams 参数,可以设置如下几种排版模式:


悬浮模板(LayoutParams.Template = 0)
第一个进入房间的用户的视频画面会铺满整个屏幕,其他用户的视频画面从左下角依次水平排列,显示为小画面。
最多4行,每行最多4个,小画面悬浮于大画面之上。
最多支持1个大画面和15个小画面。
如果用户只发送音频,仍然会占用画面位置。
九宫格模板(LayoutParams.Template = 1)
所有用户的视频画面大小一致,平分整个屏幕,人数越多,每个画面的尺寸越小。
最多支持16个画面,如果用户只发送音频,仍然会占用画面位置。
屏幕分享模板(LayoutParams.Template = 2)
适合视频会议和在线教育场景的布局。
屏幕分享(或者主讲的摄像头)始终占据屏幕左侧的大画面位置,其他用户依次垂直排列于右侧。
需要通过 LayoutParams.MainVideoUserIdLayoutParams.MainVideoStreamType 这两个参数来指定左侧主画面的内容。
最多两列,每列最多8个小画面。最多支持1个大画面和15个小画面。
如果用户只发送音频,仍然会占用画面位置。
画中画模板(LayoutParams.Template = 3)
该模板以“一大一小,一前一后”的模式混合房间中的两路画面,即将房间中一路画面铺满整个屏幕,再将一路画面作为小画面悬浮在大画面之上,小画面的位置可以通过参数指定。
您可以通过 LayoutParams 中的 MainVideoUserIdMainVideoStreamType 参数指定大画面这一路的用户 ID 和流类型。
您可以通过 LayoutParams 中的 SmallVideoLayoutParams 参数指定小画面这一路的用户 ID、流类型和布局位置等信息。
场景示例1:在线教育场景中,混合老师端摄像头(通常作为小画面)和老师端屏幕(通常作为大画面)两路画面,并混合课堂中学生的声音。
场景示例2:1v1 视频通话场景中,混合远端用户画面(通常作为大画面)和本地用户画面(通常作为小画面)。
自定义模板(LayoutParams.Template = 4)
适用于需要自定义排布各路画面位置的场景,您可以通过 LayoutParams 中的 PresetLayoutConfig 参数(这是一个数组),预先设置各路画面的位置。
您可以不指定 PresetLayoutConfig 参数中的 UserId 参数,排版引擎会根据进房的先后顺序,将进房的用户依次分配到 PresetLayoutConfig 数组中指定的各个位置上。
如果 PresetLayoutConfig 数组中的某一个被指定了 UserId 参数,则排版引擎会预先给指定的用户预留好他/她在画面中的位置。
如果用户只上行音频,不上行视频,该用户依然会占用画面位置。
PresetLayoutConfig 数组中预设的位置被用完后,排版引擎将不再混合其他用户的画面和声音。
注意:
云端混流服务最多支持同时混合16路音视频流,如果用户只有音频也会被算作一路。

步骤2:设置混流编码参数(必需)

通过 StartMCUMixTranscode 中的 EncodeParams 参数,可以设置混流编码参数:
名称
描述
推荐值
AudioSampleRate
混流-输出流音频采样率
48000
AudioBitrate
混流-输出流音频码率,单位 kbps
64
AudioChannels
混流-输出流音频声道数
2
VideoWidth
混流-输出流宽,音视频输出时必填
自定义
VideoHeight
混流-输出流高,音视频输出时必填
自定义
VideoBitrate
混流-输出流码率,单位 kbps,音视频输出时必填
自定义
VideoFramerate
混流-输出流帧率,音视频输出时必填
15
VideoGop
混流-输出流 GOP,音视频输出时必填
3
BackgroundColor
混流-输出流背景色
自定义

步骤3:指定混合后的 streamID(必需)

OutputParams.StreamId 通过该参数您可以指定混合后的音视频流在直播 CDN 上的 streamID。不过只有在您已经开通了直播服务并配置了播放域名的情况下,才能通过 CDN 正常观看这条直播流。
OutputParams.PureAudioStream 如果您只希望做纯音频直播,可以设置 OutputParams.PureAudioStream 参数为 1,代表仅把混音后的音频数据流转发到 CDN 上。

步骤4:设置是否开启云端录制(可选)

OutputParams.RecordId 该参数用于指定是否启动 云端录制,如果您指定此参数,那么混流后的音视频流会被录制成文件并存储到 云点播 中。录制下来的文件会按照 OutputParams.RecordId_开始时间_结束时间 的格式命名,例如:file001_2020-02-16-12-12-12_2020-02-16-13-13-13
OutputParams.RecordAudioOnly 如果您只希望录制音频而不需要视频内容,可以设置 OutputParams.RecordAudioOnly 参数为1,表示仅录制 MP3 格式的文件。
说明:
自2022年08月01日起,新创建应用请参考新版云端录制功能说明发起录制,StartMCUMixTranscode仅可用于旧版云端录制功能应用发起录制。如需确认当前应用的云端录制功能类型请参见新、旧录制功能类型判断方式

结束混流

由您的服务器调用 REST API StopMCUMixTranscode 即可结束混流。

方案二:客户端 SDK API 混流方案

使用 TRTC SDK 发起混流指令非常简单,只需调用各个平台的 setMixTranscodingConfig() API 即可,目前 SDK 提供了 4 种常用的混流方案:
参数项
纯音频模式(PureAudio)
预排版模式(PresetLayout)
屏幕分享模式(ScreenSharing)
全手动模式(Manual)
调用次数
只需调用一次接口
只需调用一次接口
只需调用一次接口
以下场景需调用混流接口:
有连麦者加入时
有连麦者离开时
连麦者开关摄像头时
连麦者开关麦克风时
混合内容
只混合音频
自定义设置各路内容
不混合学生端的画面
自定义设置各路内容
audioSampleRate
推荐48000
推荐48000
推荐48000
推荐48000
audioBitrate
推荐64
推荐64
推荐64
推荐64
audioChannels
推荐2
推荐2
推荐2
推荐2
videoWidth
无需设置
不能为0
推荐0
不能为0
videoHeight
无需设置
不能为0
推荐0
不能为0
videoBitrate
无需设置
不能为0
推荐0
不能为0
videoFramerate
无需设置
推荐15
推荐15
推荐15
videoGOP
无需设置
推荐3
推荐3
推荐3
mixUsers 数组
无需设置
使用占位符设置
无需设置
使用真实 userId 设置

纯音频模式(PureAudio)

适用场景

纯音频模式适用于语音通话(AudioCall)和语音聊天室(VoiceChatRoom)等纯音频应用场景,该类场景下您可以在调用 SDK 的 enterRoom 接口时进行设定。 纯音频模式下,SDK 会自动将房间里的多路音频流混合成一路。

使用步骤

1. 在调用 enterRoom() 函数进入房间时,根据您的业务需要,设定 AppScene 参数为 TRTCAppSceneAudioCallTRTCAppSceneVoiceChatRoom,明确当前房间中没有视频且只有音频。
2. 开启 旁路直播,并设定 TRTCParams 中的 streamId 参数,指定 MCU 输出的混合音频流的去处。
3. 调用 startLocalAudio() 开启本地音频采集和音频上行。
说明
由于云端混流的本质是将多路流混合到当前(即发起混流指令的)用户所对应的音视频流上,因此当前用户本身必须有音频上行才能构成混流的前提条件。
4. 调用 setMixTranscodingConfig() 接口启动云端混流,需要您在调用时将 TRTCTranscodingConfig 中的 mode 参数设定为 TRTCTranscodingConfigMode_Template_PureAudio,并指定 audioSampleRateaudioBitrateaudioChannels 等关乎音频输出质量的参数。
5. 经过上述步骤,当前用户的旁路音频流中就会自动混合房间中其他用户的声音,之后您可以参考文档 CDN 直播观看 配置播放域名进行直播观看,也可以参考文档 云端录制 录制混合后的音频流。
注意
纯音频模式下 setMixTranscodingConfig() 接口无需多次调用,在进房成功并开启本地音频上行后调用一次即可。

预排版模式(PresetLayout)

适用场景

预排版模式适用于视频通话(VideoCall)和互动直播(LIVE)等音频和视频皆有的应用场景,该类场景下您可以在调用 SDK 的 enterRoom 接口时进行设定。 预排版模式下,SDK 会自动按照您预先设定各路画面的排版规则将房间里的多路音频流混合成一路。

使用步骤

1. 在调用 enterRoom() 函数进入房间时,根据您的业务需要,设定 AppScene 参数为 TRTCAppSceneVideoCallTRTCAppSceneLIVE
2. 开启 旁路直播,并设定 TRTCParams 中的 streamId 参数,指定 MCU 输出的混合音频流的去处。
3. 调用 startLocalPreview()startLocalAudio() 开启本地的音视频上行。
说明
由于云端混流的本质是将多路流混合到当前(即发起混流指令的)用户所对应的音视频流上,因此当前用户本身必须有音视频上行才能构成混流的前提条件。
4. 调用 setMixTranscodingConfig() 接口启动云端混流,需要您在调用时将 TRTCTranscodingConfig 中的 mode 参数设定为 TRTCTranscodingConfigMode_Template_PresetLayout ,并指定 audioSampleRateaudioBitrateaudioChannels 等关乎音频输出质量的参数,以及 videoWidthvideoHeightvideoBitratevideoFramerate 等关乎视频输出质量的参数。
5. 组装 mixUser 参数,预排版模式下 mixUser 中的 userId 参数请使用 $PLACE_HOLDER_REMOTE$$PLACE_HOLDER_LOCAL_MAIN$ 以及 $PLACE_HOLDER_LOCAL_SUB$ 这三个占位字符串,其含义如下表所示:
占位符
含义
是否支持多个
$PLACE_HOLDER_LOCAL_MAIN$
指代本地摄像头这一路
不支持
$PLACE_HOLDER_LOCAL_SUB$
指代本地屏幕分享这一路(只有画面)
不支持
$PLACE_HOLDER_REMOTE$
指代远端连麦者,可以同时设置多个
支持
6. 经过上述步骤,当前用户的旁路音频流中就会自动混合房间中其他用户的声音,之后您可以参考文档 CDN 直播观看 配置播放域名进行直播观看,也可以参考文档 云端录制 录制混合后的音频流。




示例代码

您可根据下面的示例代码实现“一大二小,上下叠加”的混合效果:
iOS
Android
C++
C#
Flutter
Web
TRTCTranscodingConfig *config = [[TRTCTranscodingConfig alloc] init];
// 设置分辨率为720 × 1280, 码率为1500kbps,帧率为20FPS
config.videoWidth = 720;
config.videoHeight = 1280;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;
// 采用预排版模式
config.mode = TRTCTranscodingConfigMode_Template_PresetLayout;

NSMutableArray *mixUsers = [NSMutableArray new];
// 主播摄像头的画面位置
TRTCMixUser* local = [TRTCMixUser new];
local.userId = @"$PLACE_HOLDER_LOCAL_MAIN$";
local.zOrder = 0; // zOrder 为0代表主播画面位于最底层
local.rect = CGRectMake(0, 0, videoWidth, videoHeight);
local.roomID = nil; // 本地用户不用填写 roomID,远程需要
[mixUsers addObject:local];

// 连麦者的画面位置
TRTCMixUser* remote1 = [TRTCMixUser new];
remote1.userId = @"$PLACE_HOLDER_REMOTE$";
remote1.zOrder = 1;
remote1.rect = CGRectMake(400, 800, 180, 240); //仅供参考
remote1.roomID = @"97392"; // 本地用户不用填写 roomID,远程需要
[mixUsers addObject:remote1];

// 连麦者的画面位置
TRTCMixUser* remote2 = [TRTCMixUser new];
remote2.userId = @"$PLACE_HOLDER_REMOTE$";
remote2.zOrder = 1;
remote2.rect = CGRectMake(400, 500, 180, 240); //仅供参考
remote2.roomID = @"97392"; // 本地用户不用填写 roomID,远程需要
[mixUsers addObject:remote2];

config.mixUsers = mixUsers;
// 发起云端混流
[_trtc setMixTranscodingConfig:config];
TRTCCloudDef.TRTCTranscodingConfig config = new TRTCCloudDef.TRTCTranscodingConfig();
// 设置分辨率为720 × 1280, 码率为1500kbps,帧率为20FPS
config.videoWidth = 720;
config.videoHeight = 1280;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;

// 采用预排版模式
config.mode = TRTCCloudDef.TRTC_TranscodingConfigMode_Template_PresetLayout;
config.mixUsers = new ArrayList<>();

// 主播摄像头的画面位置
TRTCCloudDef.TRTCMixUser local = new TRTCCloudDef.TRTCMixUser();
local.userId = "$PLACE_HOLDER_LOCAL_MAIN$";
local.zOrder = 0; // zOrder 为0代表主播画面位于最底层
local.x = 0;
local.y = 0;
local.width = videoWidth;
local.height = videoHeight;
local.roomId = null; // 本地用户不用填写 roomID,远程需要
config.mixUsers.add(local);

// 连麦者的画面位置
TRTCCloudDef.TRTCMixUser remote1 = new TRTCCloudDef.TRTCMixUser();
remote1.userId = "$PLACE_HOLDER_REMOTE$";
remote1.zOrder = 1;
remote1.x = 400; //仅供参考
remote1.y = 800; //仅供参考
remote1.width = 180; //仅供参考
remote1.height = 240; //仅供参考
remote1.roomId = "97392"; // 本地用户不用填写 roomID,远程需要
config.mixUsers.add(remote1);

// 连麦者的画面位置
TRTCCloudDef.TRTCMixUser remote2 = new TRTCCloudDef.TRTCMixUser();
remote2.userId = "$PLACE_HOLDER_REMOTE$";
remote2.zOrder = 1;
remote1.x = 400; //仅供参考
remote1.y = 500; //仅供参考
remote1.width = 180; //仅供参考
remote1.height = 240; //仅供参考
remote1.roomId = "97393"; // 本地用户不用填写 roomID,远程需要
config.mixUsers.add(remote2);

// 发起云端混流
trtc.setMixTranscodingConfig(config);

TRTCTranscodingConfig config;
// 设置分辨率为1280 × 720, 码率为1500kbps,帧率为20fps
config.videoWidth = 1280;
config.videoHeight = 720;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;

// 采用预排版模式
config.mode == TRTCTranscodingConfigMode_Template_PresetLayout
TRTCMixUser* mixUsersArray = new TRTCMixUser[3];
mixUsersArray[0].userId = "$PLACE_HOLDER_LOCAL_MAIN$";
mixUsersArray[0].zOrder = 0; // zOrder 为0代表主播画面位于最底层
mixUsersArray[0].rect.left = 0;
mixUsersArray[0].rect.top = 0;
mixUsersArray[0].rect.right = videoWidth;
mixUsersArray[0].rect.bottom = videoHeight;
mixUsersArray[0].roomId = nullptr; // 本地用户不用填写 roomID,远程需要

mixUsersArray[1].userId = "$PLACE_HOLDER_REMOTE$";
mixUsersArray[1].zOrder = 1;
mixUsersArray[1].rect.left = 400; //仅供参考
mixUsersArray[1].rect.top = 800; //仅供参考
mixUsersArray[1].rect.right = 180; //仅供参考
mixUsersArray[1].rect.bottom = 240; //仅供参考
mixUsersArray[1].roomId = "97392"; // 本地用户不用填写 roomID,远程需要

mixUsersArray[2].userId = "$PLACE_HOLDER_REMOTE$";
mixUsersArray[2].zOrder = 1;
mixUsersArray[2].rect.left = 400; //仅供参考
mixUsersArray[2].rect.top = 500; //仅供参考
mixUsersArray[2].rect.right = 180; //仅供参考
mixUsersArray[2].rect.bottom = 240; //仅供参考
mixUsersArray[2].roomId = "97393"; // 本地用户不用填写 roomID,远程需要
config.mixUsersArray = mixUsersArray;

// 发起云端混流
trtc->setMixTranscodingConfig(&config);

TRTCTranscodingConfig config = new TRTCTranscodingConfig();
// 设置分辨率为1280 × 720, 码率为1500kbps,帧率为20fps
config.videoWidth = 1280;
config.videoHeight = 720;
config.videoBitrate = 1500;
config.videoFramerate = 20;
config.videoGOP = 2;
config.audioSampleRate = 48000;
config.audioBitrate = 64;
config.audioChannels = 2;
config.mode = RTCTranscodingConfigMode.TRTCTranscodingConfigMode_Template_PresetLayout;
TRTCMixUser[] mixUsersArray = new TRTCMixUser[3];

// 主播摄像头的画面位置
TRTCMixUser local = new TRTCMixUser();
local.userId = "$PLACE_HOLDER_LOCAL_MAIN$";
local.zOrder = 0; // zOrder 为0代表主播画面位于最底层
local.roomId = null; // 本地用户不用填写 roomID,远程需要
RECT rtLocal = new RECT() {
left = 0,
top = 0,
right = videoWidth,
bottom = videoHeight
};
local.rect = rtLocal;
mixUsersArray[0] = local;

// 连麦者的画面位置
TRTCMixUser remote1 = new TRTCMixUser();
remote1.userId = "$PLACE_HOLDER_REMOTE$";
remote1.zOrder = 1;
remote1.roomId =97392; // 本地用户不用填写 roomID,远程需要
RECT rtRemote1 = new RECT() { //仅供参考
left = 420,
top = 81,
right = 240 + left,
bottom = 240 + top
};
remote1.rect = rtRemote1;
mixUsersArray[1] = remote1;

// 连麦者的画面位置
TRTCMixUser remote2 = new TRTCMixUser();
remote2.userId = "$PLACE_HOLDER_REMOTE$";
remote2.zOrder = 1;
remote2.roomId =97393; // 本地用户不用填写 roomID,远程需要
RECT rtRemote2 = new RECT() { //仅供参考
left = 660,
top = 400,
right = 240 + left,
bottom = 240 + top
};
rtRemote2.rect = rtRemote2;
mixUsersArray[2] = remote2;

// 发起云端混流
config.mixUsersArray = mixUsersArray;
trtc.setMixTranscodingConfig(config);

TRTCCloud trtcCloud = await TRTCCloud.sharedInstance();
trtcCloud.setMixTranscodingConfig(TRTCTranscodingConfig(
appId: 1252463788, //仅供参考
bizId: 3891, //仅供参考
// 设置分辨率为720 × 1280, 码率为1500kbps,帧率为20FPS
videoWidth: 720,
videoHeight: 1280,
videoBitrate: 1500,
videoFramerate: 20,
videoGOP: 2,
audioSampleRate: 48000,
audioBitrate: 64,
audioChannels: 2,

// 采用预排版模式
mode: TRTCCloudDef.TRTC_TranscodingConfigMode_Template_PresetLayout,

mixUsers: [
// 主播摄像头的画面位置
TRTCMixUser(
userId: "$PLACE_HOLDER_LOCAL_MAIN$",
roomId: null, // 本地用户不用填写 roomID,远程需要
zOrder: 0, // zOrder 为0代表主播画面位于最底层
x: 0, //仅供参考
y: 0,
streamType: 0,
width: 300,
height: 400),
TRTCMixUser(
userId: '$PLACE_HOLDER_REMOTE$',
roomId: '256', // 本地用户不用填写 roomID,远程需要
zOrder: 1,
x: 100, //仅供参考
y: 100,
streamType: 0,
width: 160,
height: 200)
],
));

try {
const config = {
target: {
publishMode: PublishMode.publishMixStreamToCDN
},
encoding: {
videoWidth: 720,
videoHeight: 1280,
videoBitrate: 1500,
videoFramerate: 20,
videoGOP: 2,
audioSampleRate: 48000,
audioBitrate: 64,
audioChannels: 2,
},
// 一路本地摄像头、两路远端流的排版位置
mix: {
audioMixUserList: [
{
userId: 'jack'
},
{
userId: 'jack2'
},
{
userId: 'jack3'
}
],
videoLayoutList: [
{
width: 720,
height: 1280,
locationX: 0,
locationY: 0,
userId: 'jack', // 本地摄像头占位,传入推摄像头的 client userId
zOrder: 1
},
{
width: 180,
height: 240,
locationX: 400,
locationY: 800,
userId: 'jack2', // Web 端目前不支持预排版模式,需要传入实际的 userId
zOrder: 2
},
{
width: 180,
height: 240,
locationX: 400,
locationY: 500,
userId: 'jack3',
zOrder: 2
}
]
}
}
await trtc.startPlugin('CDNStreaming', config);
} catch (error) {
console.error('CDNStreaming start failed ', error);
}

注意
预排版模式下 setMixTranscodingConfig() 接口无需多次调用,在进房成功并开启本地音频上行后调用一次即可。
上述 Web 端是 5.x 版本的代码示例,详细教程请参考 CDNStreaming Plugin
4.x 版本请参考: Client.startMixTranscode()

屏幕分享模式(ScreenSharing)

适用场景

屏幕分享模式适用于在线教育和互动课堂等场景,该类场景下您可以在调用 SDK 的 enterRoom 接口时将 AppScene 参数设定为 TRTCAppSceneLIVE。 屏幕分享模式下,SDK 会先根据您所选定的目标分辨率构建一张画布。当老师未开启屏幕分享时,SDK 会将摄像头画面等比例拉伸绘制到该画布上;当老师开启屏幕分享后,SDK 会将屏幕分享画面绘制到同样的画布上。通过构建画布可以确保混流模块的输出分辨率一致,防止录制和网页观看的视频兼容性问题(普通播放器不支持分辨率会变化的视频)。

使用步骤

1. 在调用 enterRoom() 函数进入房间时,根据您的业务需要,设定 AppScene 参数为 TRTCAppSceneLIVE
2. 开启 旁路直播,并设定 TRTCParams 中的 streamId 参数,指定 MCU 输出的混合音视频流的去处。
3. 调用 startLocalPreview()startLocalAudio() 开启本地的音视频上行。
说明
由于云端混流的本质是将多路流混合到当前(即发起混流指令的)用户所对应的音视频流上,因此当前用户本身必须有音视频上行才能构成混流的前提条件。
4. 调用 setMixTranscodingConfig() 接口启动云端混流,需要您在调用时将 TRTCTranscodingConfig 中的 mode 参数设定为 TRTCTranscodingConfigMode_Template_ScreenSharing ,并指定 audioSampleRateaudioBitrateaudioChannels 等关乎音频输出质量的参数,以及 videoWidthvideoHeightvideoBitratevideoFramerate 等关乎视频输出质量的参数。
说明
若将 videoWidthvideoHeight 参数均指定为0,SDK 会自动根据用户当前屏幕的宽高比计算出一个合适的分辨率。
5. 经过上述步骤,当前用户的旁路音频流中就会自动混合房间中其他用户的声音,之后您可以参考文档 CDN 直播观看 配置播放域名进行直播观看,也可以参考文档 云端录制 录制混合后的音频流。



注意
屏幕分享模式下 setMixTranscodingConfig() 接口无需多次调用,在进房成功并开启本地音频上行后调用一次即可。
由于教学模式下的视频内容以屏幕分享为主,同时传输摄像头画面和屏幕分享画面非常浪费带宽。建议直接将摄像头画面和学生的画面通过 setLocalVideoRenderCallback()setRemoteVideoRenderCallback() 接口自绘到当前屏幕上。
通过将 TRTCTranscodingConfig 中的 videoWidthvideoHeight 参数均指定为 0,可以让 SDK 智能选择输出分辨率。如果老师当前屏幕宽度小于1920px,SDK 会使用老师当前屏幕的实际分辨率;如果老师当前屏幕宽度大于1920px,SDK 会根据当前屏幕宽高比,选择 1920 × 1080(16:9)、1920 × 1200(16:10)或1920 × 1440(4:3)。

全手动模式(Manual)

适用场景

全手动模式适合于上述自动模式均不适用的场景,全手动的灵活性最高,可以自由组合出各种混流方案,但易用性最差。 全手动模式下,您需要设置 TRTCTranscodingConfig 中的所有参数,并需要监听 TRTCCloudDelegate 中的 onUserVideoAvailable()onUserAudioAvailable() 回调,以便根据当前房间中各个上麦用户的音视频状态不断地调整 mixUsers 参数,否则会导致混流失败。

使用步骤

1. 在调用 enterRoom() 函数进入房间时,根据您的业务需要,设定 AppScene 参数。
2. 开启 旁路直播,并设定 TRTCParams 中的 streamId 参数,指定 MCU 输出的混合音视频流的去处。
3. 根据您的业务需要,调用 startLocalAudio() 开启本地的音频上行(或同时调用 startLocalPreview() 开启视频上行)。
说明
由于云端混流的本质是将多路流混合到当前(即发起混流指令的)用户所对应的音视频流上,因此当前用户本身必须有音视频上行才能构成混流的前提条件。
4. 调用 setMixTranscodingConfig() 接口启动云端混流,需要您在调用时将 TRTCTranscodingConfig 中的 mode 参数设定为 TRTCTranscodingConfigMode_Manual ,并指定 audioSampleRateaudioBitrateaudioChannels 等关乎音频输出质量的参数。如果您的业务场景中也包含视频,需同时设置 videoWidthvideoHeightvideoBitratevideoFramerate 等关乎视频输出质量的参数。
5. 监听 TRTCCloudDelegate 中的 onUserVideoAvailable()onUserAudioAvailable() 回调,并根据需要指定mixUsers参数。
说明
与预排版(PresetLayout)模式不同,Manual 需要您指定每一个 mixUser 中的 userId 参数为真实的连麦者 ID,并且也要根据该连麦者是否开启了视频,如实设定 mixUser 中的 pureAudio 参数。
6. 经过上述步骤,当前用户的旁路音频流中就会自动混合房间中其他用户的声音,之后您可以参考文档 CDN 直播观看 配置播放域名进行直播观看,也可以参考文档 云端录制 录制混合后的音频流。
注意
全手动模式下,您需要实时监听房间中连麦者的上麦下麦动作,并根据连麦者的人数和音视频状态,多次调用 setMixTranscodingConfig() 接口。

相关费用

费用的计算

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

费用的节约

基于服务端 REST API 混流方案下,要停止混流,需要满足如下条件之一:
房间里的所有用户(包括主播和观众)都退出了房间。
调用 REST API StopMCUMixTranscode 主动停止混流。
基于客户端 SDK API 混流方案下,要停止混流,需要满足如下条件之一:
发起混流(即调用了客户端 API setMixTranscodingConfig)的主播退出了房间。
调用 setMixTranscodingConfig 并将参数 config 设置为 nil/null 主动停止混流。
在其他情况下,TRTC 云端都将会尽力持续保持混流状态。因此,为避免产生预期之外的混流费用,请在您不需要混流的时候尽早通过上述方法结束云端混流。