?譯者 | 朱鋼
審校 | 孫淑娟
流混合是一種將多個(gè)音頻或視頻流組合到云上的一個(gè)流技術(shù),廣泛應(yīng)用于直播、在線教育、音頻室直播等場(chǎng)景。開發(fā)人員可以通過播放混合流來查看屏幕并聽到聊天室中所有成員的聲音,無需管理聊天室中的每個(gè)流。
流混合的優(yōu)勢(shì)
流混合之所以廣泛應(yīng)用于音頻和視頻領(lǐng)域,是因?yàn)樗梢越o開發(fā)人員帶來以下好處。
1. 低成本
在大型直播或在線教育場(chǎng)景中,如果多方在一個(gè)房間內(nèi)共同主持,房間內(nèi)的所有用戶需要播放多條流。使用流混合技術(shù),只需要播放一個(gè)流。即在雙方托管的情況下,費(fèi)用可減半。在多方托管的情況下,成本可以降低(n - 1)/n。如果使用審查機(jī)制(比如淫穢內(nèi)容審核),成本也可以降低(n - 1) /n,因?yàn)橹恍枰榭匆粋€(gè)流的圖像。
2. 簡(jiǎn)單的代碼邏輯
當(dāng)多個(gè)主機(jī)共同托管并使用流混合時(shí),觀眾只需播放混合流并進(jìn)行渲染,而不是播放和渲染多個(gè)流。
3.在不同平臺(tái)之間輕松轉(zhuǎn)發(fā)
如果沒有流混合,我們無法在多方共同托管方案中將直播轉(zhuǎn)發(fā)到 Facebook?、YouTube 和其他直播流平臺(tái)。因?yàn)檫@些平臺(tái)只有一個(gè) RTMP 地址,我們無法將多個(gè)流轉(zhuǎn)發(fā)到一個(gè)地址。
4. 移動(dòng)客戶端上的 Web 瀏覽器支持的多方共同托管
對(duì)于 iPhone 用戶,Safari 瀏覽器不支持同時(shí)播放多個(gè)音頻文件。當(dāng)播放多個(gè)流時(shí),就只能播放一個(gè)流,流混合可以解決這個(gè)問題。由于手機(jī)性能和瀏覽器性能的限制,手機(jī)上的大多數(shù)Web瀏覽器一般可以播放最多四個(gè)流。借助流混合技術(shù),可以播放的最大流數(shù)會(huì)有很大的增加,并且無需額外的帶寬和性能消耗。
什么是流混合
如下圖所示,當(dāng)一個(gè)聊天室中的多個(gè)用戶發(fā)布流時(shí),服務(wù)器會(huì)根據(jù)布局配置將兩個(gè)流合并為一個(gè)流,這樣觀眾就可以播放混合流查看用戶 A 和用戶 B 的屏幕。
流混合的實(shí)現(xiàn)
1. 流體混合工藝
a) 服務(wù)器偵聽聊天室中的流變更;
b) 客戶端上的主機(jī)發(fā)布流;
c) 當(dāng)服務(wù)器檢測(cè)到第一個(gè)新流時(shí),它將開始執(zhí)行流混合操作;
d) 共同托管開始發(fā)布流;
e) 服務(wù)器檢測(cè)流添加并更新布局配置;
f) 共同托管停止;
g) 服務(wù)器檢測(cè)流減少并更新布局配置;
h) 房間解散,混音任務(wù)停止。
2. 客戶端邏輯
客戶端不需要管理流混合邏輯。它只需要根據(jù)是否需要發(fā)布流來確定是播放原始流還是混合流,如下圖所示。
3. 服務(wù)器邏輯
服務(wù)器需要偵聽房間中的流更改,并在添加或減少流時(shí)更新流混合配置。根據(jù)要求,布局配置隨流的數(shù)量而變化。當(dāng)流數(shù)為 0 時(shí),需要停止流混合。
4. 布局配置
ZEGOCLOUD提供了一個(gè)布局配置API。開發(fā)人員只需設(shè)置每個(gè)流的位置和大小。以下示例是一些主要代碼。在示例中,視頻屏幕布局的分辨率設(shè)置為 360 × 640。
布局 1:兩個(gè)視圖并排顯示
/** 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:垂直平鋪四個(gè)視圖
/** 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:平鋪一個(gè)大視圖,懸浮兩個(gè)小視圖
輸入流的圖層級(jí)別由輸入流在輸入流列表中的位置確定。列表中的順序越靠后,圖層級(jí)別越高。如下代碼所示,輸入流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社區(qū)編輯,2021年IT影響力專家博主,阿里云專家博主,2019年CSDN博客之星20強(qiáng),2020年騰訊云+社區(qū)優(yōu)秀作者,11年一線開發(fā)經(jīng)驗(yàn),曾參與獵頭服務(wù)網(wǎng)站架構(gòu)設(shè)計(jì),企業(yè)智能客服以及大型電子政務(wù)系統(tǒng)開發(fā),主導(dǎo)某大型央企內(nèi)部防泄密和電子文檔安全監(jiān)控系統(tǒng)的建設(shè),目前在北京圖伽健康從事醫(yī)療軟件研發(fā)工作。
原文標(biāo)題:??Improve live streaming experience with stream mixing???,作者:DavidRelo?