译者 | 朱钢
审校 | 孙淑娟
流混合是一种将多个音频或视频流组合到云上的一个流技术,广泛应用于直播、在线教育、音频室直播等场景。开发人员可以通过播放混合流来查看屏幕并听到聊天室中所有成员的声音,无需管理聊天室中的每个流。
流混合的优势
流混合之所以广泛应用于音频和视频领域,是因为它可以给开发人员带来以下好处。
1. 低成本
在大型直播或在线教育场景中,如果多方在一个房间内共同主持,房间内的所有用户需要播放多条流。使用流混合技术,只需要播放一个流。即在双方托管的情况下,费用可减半。在多方托管的情况下,成本可以降低(n - 1)/n。如果使用审查机制(比如淫秽内容审核),成本也可以降低(n - 1) /n,因为只需要查看一个流的图像。
2. 简单的代码逻辑
当多个主机共同托管并使用流混合时,观众只需播放混合流并进行渲染,而不是播放和渲染多个流。
3.在不同平台之间轻松转发
如果没有流混合,我们无法在多方共同托管方案中将直播转发到 Facebook、YouTube 和其他直播流平台。因为这些平台只有一个 RTMP 地址,我们无法将多个流转发到一个地址。
4. 移动客户端上的 Web 浏览器支持的多方共同托管
对于 iPhone 用户,Safari 浏览器不支持同时播放多个音频文件。当播放多个流时,就只能播放一个流,流混合可以解决这个问题。由于手机性能和浏览器性能的限制,手机上的大多数Web浏览器一般可以播放最多四个流。借助流混合技术,可以播放的最大流数会有很大的增加,并且无需额外的带宽和性能消耗。
什么是流混合
如下图所示,当一个聊天室中的多个用户发布流时,服务器会根据布局配置将两个流合并为一个流,这样观众就可以播放混合流查看用户 A 和用户 B 的屏幕。
流混合的实现
1. 流体混合工艺
a) 服务器侦听聊天室中的流变更;
b) 客户端上的主机发布流;
c) 当服务器检测到第一个新流时,它将开始执行流混合操作;
d) 共同托管开始发布流;
e) 服务器检测流添加并更新布局配置;
f) 共同托管停止;
g) 服务器检测流减少并更新布局配置;
h) 房间解散,混音任务停止。
2. 客户端逻辑
客户端不需要管理流混合逻辑。它只需要根据是否需要发布流来确定是播放原始流还是混合流,如下图所示。
3. 服务器逻辑
服务器需要侦听房间中的流更改,并在添加或减少流时更新流混合配置。根据要求,布局配置随流的数量而变化。当流数为 0 时,需要停止流混合。
4. 布局配置
ZEGOCLOUD提供了一个布局配置API。开发人员只需设置每个流的位置和大小。以下示例是一些主要代码。在示例中,视频屏幕布局的分辨率设置为 360 × 640。
布局 1:两个视图并排显示
/** Create an input stream list. */
ArrayList<ZegoMixerInput> inputList = new ArrayList<>();
/** Configue the first input stream, including the streamID (the real ID of the input stream), input type, layout, etc.*/
ZegoMixerInput input_1 = new ZegoMixerInput("streamID_1", ZegoMixerInputContentType.VIDEO, new Rect(0, 0, 180, 640));
inputList.add(input_1);
/** Configue the second input stream. */
ZegoMixerInput input_2 = new ZegoMixerInput("streamID_2", ZegoMixerInputContentType.VIDEO, new Rect(180, 0, 360, 640));
inputList.add(input_2);
/** Set up the input steam list for the 流混合 task. */
task.setInputList(inputList);
布局 2:垂直平铺四个视图
/** Create an input stream list. */
ArrayList<ZegoMixerInput> inputList = new ArrayList<>();
/** Configue the first input stream, including the streamID (the real ID of the input stream), input type, layout, etc.*/
ZegoMixerInput input_1 = new ZegoMixerInput("streamID_1", ZegoMixerInputContentType.VIDEO, new Rect(0, 0, 180, 320));
inputList.add(input_1);
/** Configue the second input stream. */
ZegoMixerInput input_2 = new ZegoMixerInput("streamID_2", ZegoMixerInputContentType.VIDEO, new Rect(180, 0, 360, 320));
inputList.add(input_2);
/** Configue the third input stream. */
ZegoMixerInput input_3 = new ZegoMixerInput("streamID_3", ZegoMixerInputContentType.VIDEO, new Rect(0, 320, 180, 640));
inputList.add(input_3);
/** Configue the fourth input stream. */
ZegoMixerInput input_4 = new ZegoMixerInput("streamID_4", ZegoMixerInputContentType.VIDEO, new Rect(180, 320, 360, 640));
inputList.add(input_4);
/** Set up the input steam list for the stream mixing task. */
task.setInputList(inputList);
布局 3:平铺一个大视图,悬浮两个小视图
输入流的图层级别由输入流在输入流列表中的位置确定。列表中的顺序越靠后,图层级别越高。如下代码所示,输入流2和输入流3的层高于输入流1的层,因此流2和流3 悬停在输入流1的屏幕上。
/** Create an input stream list. */
ArrayList<ZegoMixerInput> inputList = new ArrayList<>();
/** Configue the first input stream, including the streamID (the real ID of the input stream), input type, layout, etc.*/
ZegoMixerInput input_1 = new ZegoMixerInput("streamID_1", ZegoMixerInputContentType.VIDEO, new Rect(0, 0, 360, 640));
inputList.add(input_1);
/** Configue the second input stream. */
ZegoMixerInput input_2 = new ZegoMixerInput("streamID_2", ZegoMixerInputContentType.VIDEO, new Rect(230, 200, 340, 400));
inputList.add(input_2);
/** Configue the third input stream. */
ZegoMixerInput input_3 = new ZegoMixerInput("streamID_3", ZegoMixerInputContentType.VIDEO, new Rect(230, 420, 340, 620));
inputList.add(input_3);
/** Set up the input steam list for the stream mixing task. */
task.setInputList(inputList);
译者介绍
朱钢,51CTO社区编辑,2021年IT影响力专家博主,阿里云专家博主,2019年CSDN博客之星20强,2020年腾讯云+社区优秀作者,11年一线开发经验,曾参与猎头服务网站架构设计,企业智能客服以及大型电子政务系统开发,主导某大型央企内部防泄密和电子文档安全监控系统的建设,目前在北京图伽健康从事医疗软件研发工作。
原文标题:Improve live streaming experience with stream mixing,作者:DavidRelo