混流是把多路音视频流从云端合并成一路流的技术,也称合流。开发者只需要拉取合并后的流就能看到房间内所有成员的画面,听到房间内所有成员的声音,无需分别管理房间内的每一条流。
本篇文档主要介绍通过客户端发起混流的操作说明,如果你需要通过自己的服务端发起混流,请参考 服务端 API - 开始混流。
ZEGO 支持手动混流、自动混流和全自动混流三种方式,三种混流方式的区别如下:
混流方式 | 手动混流 |
自动混流 |
全自动混流 |
---|---|---|---|
含义 | 自定义控制混流任务和混流内容,包括输入流、混流布局等。支持手动混视频流和音频流。 |
指定房间,自动将房间内的所有音频流进行混流。只支持自动混音频流。 |
每个房间都自动混音频流。只支持全自动混音频流。 |
应用场景 | 合并多个视频画面和声音时可用,比如在线课堂中老师和学生画面的直播,娱乐场景中的跨房间连麦,特殊场景中需混合指定几条流等;设备不支持同时拉多条流或者设备性能较差的场景。 |
将房间内所有音频流合为一条流时使用自动混流,比如语聊房、合唱。 |
不想做任何开发,房间内所有音频流合为一条流时使用全自动混流,比如语聊房、合唱。 |
优势 | 灵活性强,能够根据业务需要实现逻辑。 |
降低了开发者接入的复杂程度,不需要管理指定房间音频流的生命周期。 |
开发者接入复杂程度很低,不需要管理所有房间音频混流任务的生命周期以及音频流的生命周期。 |
发起方式 | 用户客户端或用户服务端发起混流任务,用户客户端维护流的生命周期。 |
用户客户端发起混流任务,ZEGO 服务端自动维护房间内流的生命周期(即输入流列表)。 |
联系 ZEGO 技术支持开通全自动混流,ZEGO 服务端维护混流任务和房间内流的生命周期(即输入流列表)。 |
请参考 下载示例源码 获取源码。
相关源码请查看 “src/Examples/Others/StreamMixing” 目录下的文件。
在实现混流功能之前,请确保:
混流功能不是默认开启的,使用前请在 ZEGO 控制台 自助开通(开通步骤请参考 项目管理 - 服务配置 中的“混流”),或联系 ZEGO 技术支持开通。
手动混流可自定义控制混流任务和混流内容,包括输入流、混流布局等,常用于多人互动直播和跨房间连麦场景。支持手动混视频流和音频流。
开发者可通过 SDK 或 ZEGO 服务端 API 实现手动混流功能,服务端相关接口请参考 开始混流 和 停止混流。
以下介绍如何使用 SDK 实现手动混流。
混流的主要流程:
按照上述流程,SDK API 调用过程如下文所示。
主播端推流后混流的前置条件为推流,请参考 快速开始 - 实现流程 的 “推流”。
根据实际业务场景,调用 ZegoMixStreamConfig 中 inputList 的定义输入的视频流列表,列表中是 ZegoMixStreamInput 对象,表示为 “streamID” 的流。根据所需的输入流个数构建 N 个 ZegoMixStreamInput 放入输入流列表。
ZegoMixStreamInput[] inputStreamInfo = {streamInfoA, streamInfoB}
。ZegoMixStreamInput 的使用示例:
输入流的布局以输出混流画面的左上角为坐标系原点,参考原点设置输入流的布局,即传入输入流的 “layout” 参数。此外,输入流的图层层次由输入流在输入流列表中的位置决定,在列表中的位置越后,表示图层层次越高。
“layout” 参数说明如下:
参数 | 描述 |
---|---|
left |
对应输入流画面左上角的 x 坐标。 |
top |
对应输入流画面左上角的 y 坐标。 |
right |
对应输入流画面右下角的 x 坐标。 |
bottom |
对应输入流画面右下角的 y 坐标。 |
假设指定某条流的左上角坐标为 (50, 300),右下角坐标为 (200, 450),这条流在最终的输出混流中的位置如下图所示:
/**
* 原点在左上角,top/bottom/left/right 定义如下:
*
* (left, top)-----------------------
* | |
* | |
* | |
* | |
* -------------------(right, bottom)
*/
// inputList 参数设置
const inputList = [
// 画面A
{
streamID: "streamA",
layout: {
top: 0,
left: 0,
bottom: 375,
right: 667,
},
},
//画面B
{
streamID: "streamB",
layout: {
top: 300,
left: 50,
bottom: 450,
right: 200,
},
},
];
开发者可参考以下示例代码实现常见的混流布局:两个画面水平平铺、四个画面水平垂直平铺、一个大画面铺满和两个小画面悬浮。
以下布局示例皆以 360×640 分辨率进行说明。
// 设置inputList
const inputList = [
{
streamID: "streamA", // 左边的流
layout: {
top: 0,
left: 0,
bottom: 640,
right: 180,
},
},
{
streamID: "streamB", // 右边的流
layout: {
top: 0,
left: 180,
bottom: 640,
right: 360,
},
}
]
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
// 设置inputList
const inputList = [
{
streamID: "streamA", // 左上角的流
layout: {
top: 0,
left: 0,
bottom: 320,
right: 180,
},
},
{
streamID: "streamC", // 左下角的流
layout: {
top: 320,
left: 0,
bottom: 640,
right: 180,
},
},
{
streamID: "streamB", // 右上角的流
layout: {
top: 0,
left: 180,
bottom: 320,
right: 360,
},
},
{
streamID: "streamD", // 右下角的流
layout: {
top: 320,
left: 180,
bottom: 640,
right: 360,
},
}
]
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
输入流的图层层次由输入流在输入流列表中的位置决定,在列表中的位置越后,表示图层层次越高。如以下示例代码所示,第 2 条输入流的图层层次和第 3 条输入流的图层层次则比第 1 条输入流的层次要高,则第 2 条和第 3 条流悬浮第 1 条流的画面上。
// 设置inputList
const inputList = [
{
streamID: "streamA", // 第一条流
layout: {
top: 0,
left: 0,
bottom: 640,
right: 320,
},
},
{
streamID: "streamB", // 第二条流
layout: {
top:200,
left:230,
bottom:400,
right: 340,
},
},
{
streamID: "streamC", // 第三条流
layout: {
top:420,
left:230,
bottom:620,
right: 340,
},
}
]
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
在混流参数 “outputList” 中,输出流的 target 可为流名 “streamID” 或 “URL”。如果需要将流推到 CDN 上,采用 “URL”;不需要将流推到 CDN 上时,由调用者决定采用 “URL” 或者 “streamID”。 "outputConfig" 参数可设置输出流的分辨率、帧率、码率、音频编码等。
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
如果需要水印图片的 URL,请联系 ZEGO 技术支持获取。
以下代码演示设置一个 ZEGO 的图片水印放置于画面左上角:
// 设置水印图片
const watermark = [
{
imageURL: "preset-id://zegowp.png",
layout: {
top: 0,
left: 0,
bottom: 100,
right: 200,
},
}
]
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
watermark,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
如果需要背景图片 ZegoMixerImageInfo 的 URL,请联系 ZEGO 技术支持获取, 或者可以用网络图片,但只支持 HTTP 协议的。
// 设置inputList
const inputList = [
{
streamID: "streamA", // 左边的流
layout: {
top: 0,
left: 0,
bottom: 640,
right: 180,
},
// 设置混流背景图片
imageInfo: {
url: "preset-id://zegobg.png",
displayMode: 1, // 当关闭摄像头时才展示背景图片,具体参数值可以查看接口文档
}
}
]
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
inputList,
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
可通过设置 enableSoundLevel 参数选择是否开启混流的声浪回调通知,开启后(取值为 “True”)用户拉混流时可通过 mixerSoundLevelUpdate 回调收到每条单流的音量变化(声浪)信息。
// 开始混流
const result = await zg.startMixerTask({
taskID:'taskUUID',
// 开启混流的声浪回调通知,开启后拉混流时可通过 [onMixerSoundLevelUpdate] 回调收到每条单流的声浪信息
enableSoundLevel: true,
inputList: {
streamID: "streamA", // 左边的流
layout: {
top: 0,
left: 0,
bottom: 640,
right: 180,
},
soundLevelID: 1, //混流音浪 ID,用于在 [mixerSoundLevelUpdate] 中找对应输入流的音浪值。
},
// 设置混流输出
outputList:['mixStreamID'],
outputConfig: {
outputBitrate: 300,
outputFPS: 15,
outputWidth: 360,
outputHeight: 640,
}
})
在推流成功后,调用 startMixerTask 将混流配置发送至 ZEGO 混流服务器,并触发混流。
const result = await zg.startMixerTask(config)
if(result.errorCode !== 0) {
//混流失败
console.error(result.extendedData)
}
如果要混流纯音频数据,部分参数配置会有如下特殊处理:
当混流信息发生变更时,例如混流的输入流列表发生增减、调整混流视频输出码率等,修改该混流任务对象的参数,然后再调用一次 startMixerTask 即可更新 ZEGO 混流服务器上的混流配置。
更新混流任务的配置时,“taskID” 不可更改。
常见错误码及含义如下:
错误码 | 说明 |
---|---|
errorCode = 150 | 混流的输入流不存在,请检查输入流是否正常。 |
errorCode = 151 | 混流失败,请检查混流流程是否处理正常。 |
errorCode = 152 | 停止混流失败,请检查混流流程是否处理正常。 |
errorCode = 153 | 输入参数错误,请检查输入参数是否正确。 |
errorCode = 154 | 输出参数错误,请检查输出参数是否正确。 |
errorCode = 155 | 输入分辨率格式错误,请检查输入分辨率格式是否正确。 |
errorCode = 156 | 输出分辨率格式错误,请检查输出分辨率格式是否正确。 |
errorCode = 157 | 混流没开,请检查是否开启混流模式。 |
停止混流是通过调用 stopMixerTask 实现。
开始混流和停止混流使用的 “taskID” 需要保持一致。
try {
await zg.stopMixerTask(taskID);
alert('停止混流成功。。。');
} catch (err) {
alert('停止混流失败。。。');
console.log('stopMixStream err: ', err);
}
请参考 快速开始 - 实现流程 的 “创建引擎” 和 “登录房间”。
ZegoAutoMixerTask 是 SDK 中定义的自动混流任务配置对象,通过配置该对象可定制化自动混流任务。
新建一个自动混流任务对象,然后分别设置输入、输出等参数。
zg.startAutoMixerTask({
taskID, // 自动混流任务的任务 ID
roomID: "room1", // 自动混流任务的房间 ID
audioConfig: {
bitrate: 64,
channel: 2,
codecID: 6
},
outputList: [
// 自动混流输出列表
{
target: mixStreamID
}
],
enableSoundLevel: true
})
.then(res => {
console.warn("startAutoMixer", res);
})
.catch(e => {
console.error("startAutoMixer", e);
});
}
通过 ZegoMixerAudioConfig 设置自动混流音频相关配置,主要包括音频码率、声道数、编码 ID,以及多路音频流混音模式。
zg.startAutoMixerTask({
taskID, // 自动混流任务的任务 ID
roomID: "room1", // 自动混流任务的房间 ID
// 音频配置
audioConfig: {
bitrate: 64, // 音频码率
channel: 2, // 音频声道数
codecID: 6
},
outputList: [
// 自动混流输出列表
{
target: mixStreamID
}
]
})
.then(res => {
console.warn("startAutoMixer", res);
})
.catch(e => {
console.error("startAutoMixer", e);
});
通过 channel 参数可以修改音频声道,目前支持如下音频声道:
枚举值 | 说明 | 适用场景 |
---|---|---|
1 | 单声道。 | 只有单声道的场景。 |
2 | 双声道。 | 有双声道的场景。 |
通过 codecID 参数可以修改编码 ID,目前支持如下编码 ID:
枚举值 | 说明 | 适用场景 |
---|---|---|
1 |
|
可用于 RTC 和 CDN 推流。 |
2 |
|
可用于 RTC 和 CDN 推流。 |
6 |
|
仅可用于 RTC 推流。 |
可通过设置 enableSoundLevel 参数选择是否开启自动混流的声浪回调通知,开启后(取值为 “True”)用户拉混流时可通过 AutoMixerSoundLevelUpdate 回调收到每条单流的音量变化(声浪)信息。
zg.startAutoMixerTask({
taskID, // 自动混流任务的任务 ID
roomID: "room1", // 自动混流任务的房间 ID
outputList: [
{
target: mixStreamID
}
],
enableSoundLevel: true
})
.then(res => {
console.warn("startAutoMixer", res);
})
.catch(e => {
console.error("startAutoMixer", e);
});
调用 stopAutoMixerTask 接口停止自动混流。
在同一个房间内开启下一个自动混流任务前,请先调用 stopAutoMixerTask 接口结束上一次自动混流任务,以免造成当一个主播已经开启下一个自动混流任务与其他主播混流时,观众依然在一直拉上一个自动混流任务的输出流的情况。若用户未主动结束当前自动混流任务,该任务将在房间关闭后自动结束。
// 传入之前创建的混流任务对象
zg.stopAutoMixerTask({
taskID: taskID,
roomID: "room1",
})
.then(res => {
console.warn("stopAutoMixerTask", res);
})
.catch(e => {
console.error("stopAutoMixerTask", e);
});
通过 ZEGO 服务端的配置实现每个房间都自动混音频流,详情请联系 ZEGO 技术支持。
联系我们
文档反馈