?譯者 | 朱鋼
審校 | 孫淑娟
流混合是一種將多個音頻或視頻流組合到云上的一個流技術,廣泛應用于直播、在線教育、音頻室直播等場景。開發人員可以通過播放混合流來查看屏幕并聽到聊天室中所有成員的聲音,無需管理聊天室中的每個流。
流混合的優勢
流混合之所以廣泛應用于音頻和視頻領域,是因為它可以給開發人員帶來以下好處。
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?