技術實踐 | 網易雲信視訊轉碼提速之分片轉碼
在媒體內容傳播行業中,視訊作為資訊傳播的載體,其重要性佔比越來越高。通常,為了應對不同的播放場景,視訊需要修改封裝容器格式、編碼格式以及解析度、位元速率等媒體流屬性,這些處理的過程我們統稱其為視訊轉碼。
網易雲信集網易 21 年 IM 以及音視訊技術,對外提供行業一流的融合通訊雲服務。其中,雲信的點播服務,基於分散式處理叢集和大規模分發系統資源,可滿足全終端裝置的播放需求,為企業使用者提供極速穩定的視訊上傳、儲存、轉碼、播放和下載等雲服務功能。雲信的分散式任務處理系統,則承載了其中的媒體處理這一能力,主要功能有音視訊的轉封裝、轉碼、合併、截圖、加密、加減水印等,以及影象伸縮、影象增強、音量歸一化等一系列前處理功能。
視訊轉碼作為媒體處理的核心功能,在對大視訊檔案轉碼時,通常需要花費較長時間,為了提升服務質量,我們將重點提升視訊轉碼的速率。本次文章將以分片轉碼為主,介紹網易雲信在轉碼提速方面的努力與效果提升。
轉碼效能的影響因子與優化
常見的視訊轉碼流程,一般如下圖所示:
在轉碼過程中,瓶頸主要在視訊流,因此我們對速度提升的討論主要針對視訊流處理,音訊流處理暫不在考慮範圍內。針對視訊流處理的環節,從以下幾個方面展開討論:
-
源視訊:一般源視訊越長,那麼編解碼所需時間則越長。
-
封裝與編解碼:對於視訊轉封裝、關鍵幀片段裁剪等不需要解碼編碼的處理,其所需計算量很小,一般耗時在1~2s。若需要重新編解碼,則根據源視訊、編碼輸出引數的不同,所耗時間也不同。常見的有編碼格式以及位元速率、解析度、幀率,比如不同編碼演算法的壓縮率與計算複雜度不一樣,導致所需耗時也有所不同,舉例來說 AV1 編碼時間就大於 H.264 的編碼時間。目標位元速率、解析度、幀率等引數越大,通常計算耗時更大。
-
計算資源的水平與垂直伸縮:通用處理器的單核計算能力越強,轉碼耗時肯定越小。利用 GPU 這類更適合影象計算處理的專用處理器,也有利於降低轉碼耗時。提升轉碼執行流的併發計算度,也有利於降低轉碼耗時。這裡的併發路數可以是多執行緒和多程序,多執行緒指單程序內以多執行緒的方式提升,多程序則為通過對檔案切片後,多程序對多個切片檔案計算。
-
叢集任務排程:多租戶的雲服務系統,通常都是基於租戶間資源分配優先順序和租戶內轉碼任務優先順序綜合而設計的排程演算法,排程效率主要在以下幾個方面體現:如何用更少的時間排程多的任務,如何用更少的叢集資源實現高吞吐量,如何做好優先順序和防飢餓的權衡設計。
針對上述的影響因素,我們提出以下幾個優化方向:提升硬體能力、優化編碼、分片轉碼以及提升叢集排程效率。
專用硬體加速
多媒體處理是典型的計算密集型場景,優化多媒體應用程式的整體計算效能至關重要。CPU 是一種通用計算資源,將視訊影象類運算 offload 到專用硬體上是一種常見的方案。目前,業內諸如 Intel、NVIDIA、AMD、ARM、TI 等晶片廠商都有相應的多媒體硬體加速方案,提升高位元速率、高解析度等視訊場景的編碼效率。
我們的轉碼系統主要基於 FFmpeg 多媒體處理框架,在 Linux 平臺上支援的廠商方案有諸如 Intel 的 VA-API (Video Acceleration API)和 Nvidia 的 VDPAU (Video Decode and Presentation API for Unix ),同時兩家廠商也支援了相對更私有的 Intel Quick Sync Video 和 NVENC/NVDEC 加速方案。目前我們主要採用了 Intel 核芯顯示卡的視訊加速能力,結合 FFmpeg 社群的 QSV Plugin 和 VAPPI Plugin 兩種方式,針對 AVDecoder、AVFilter、AVEncoder 三個模組做了硬體加速。硬體加速相關技術,相關廠商和社群都在持續優化,在我們的後續系列文章中,我們也會詳細介紹這塊的進一步實踐。
AMD 大核伺服器
這裡主要指搭載了 AMD EPYC 系列處理器的伺服器,相對於我們此前線上的伺服器,其單核計算力更強,平行計算能力更優異。單核計算力的提升讓我們在解碼、前處理、編碼能有整體性的通用提升,而搭載超大核則是讓我們的分片轉碼方案中的單機多程序場景更加如虎添翼,大大避免了媒體資料的跨機器IO通訊。
自研 Codec
NE264/NE265 是網易雲信自主研發的視訊編碼器,在雲信的 NERTC、直播點播中都有所應用。除了編碼效能的提升之外,NE264 更重要的技術優勢是低頻寬高畫質,其適用於高位元速率高清晰度直播場景(如:遊戲直播、線上演唱會、產品釋出會等),可以確保人眼主觀畫面質量不變的情況下,平均節省 20%~30% 的位元速率。這裡不再展開介紹,有興趣的可以關注網易智企技術+微信公眾號。
分片轉碼
如果說上面的幾種效能優化手段是垂直的,那麼本節所說的分片轉碼則是水平的。視訊流本質就是一連串的影象組成,並以 IDR 幀為邊界劃分成一串 GOP,每個 GOP 就是獨立的一組影象集。視訊檔案的這一內容特點,決定了我們可以參考 MapReduce 的演算法思路,將視訊檔案切割為多個分片,然後並行地對分片進行轉碼,最後再合併成一個完整的檔案。
任務排程
除了對單個轉碼計算執行流優化之外,我們也需要提升叢集資源的整體排程效率。在排程演算法這塊,排程節點既要接收任務提交,又要完成任務下發的關鍵流程,這個任務下發的演算法設計需要做好多租戶分配、任務優先順序搶佔和儘量提升叢集資源利用率的多方平衡。
我們設計了兩種任務下發的機制:
-
Master 節點 push 任務到計算節點
-
計算節點主動來 Master 節點 pull 任務
前者的優點是實時性更高,缺點則是 Master 對計算節點的資源視角是一種 snapshot 快照,有些情況下該快照資訊的滯後性會導致部分節點的過載現象。後者的優點則是節點按需取任務來執行,不會出現部分節點過載的現象,同時在任務選擇性這塊的可程式設計性更加便利,而缺點則是 Master 對全域性資源分配的實時力度掌控性不足。
分片轉碼方案實踐
媒體流程
媒體處理的簡易流程如下圖所示,主要分四個步驟:分片前轉封裝(按需)、視訊分片、並行轉碼、視訊合併。
分片流程
在叢集資源充足的情況下,即任務的排程與分發一般不會有積壓和資源搶佔現象,這種情況下視訊流本身的處理計算,一般會消耗整個任務週期 80%-90% 的時間,所以針對這一階段進行優化,可以有更高性價比的收益。
提升硬體能力、優化編碼這兩個維度是針對提升單個轉碼程序的計算效率,但是單程序能呼叫的資源有限,對大視訊檔案的速率提升也是很有限。因此,在這裡我們探討如何採用分散式 MapReduce 的思想,縮短一個轉碼任務所消耗的時間。接下來的章節將詳細講述實現分片轉碼技術方案。
分片轉碼流程基礎架構如上圖,我們首先介紹以下幾個概念:
- 父任務:類似於 Hadoop 中的 Job,客戶端提交的轉碼 Job,需將其待轉碼的視訊拆分成多個小分片;
- 子任務:類似於 Hadoop 中的 Task,將多個小分片包裝成可以獨立排程和執行的 Task 子任務;
- 父 Worker:執行父任務的計算節點;
- 子 Worker:執行子任務的計算節點。
分片轉碼的主要流程:
- Dispatch center 給 worker0 派發一個轉碼 job,worker0 根據總開關、job 配置、視訊檔案大小等策略判斷是否進行分片轉碼;
- 如果確定進行分片轉碼,則進行分成 n 片;
- 包裝成 n 個轉碼Task提交給 Dispatch center;
- Dispatch center 將這 n 個轉碼子任務排程給符合要求的 n 個 worker;
- worker1~n 轉碼完成後,給 worker0 傳送回撥;
- worker0 分別從 n 個 worker 上下載轉碼後的分片視訊,待所有分片轉碼完成,將轉碼後的分片合併在一起;
- 傳送回撥給 client。
子任務排程
在排程系統中,每個使用者的任務佇列是獨立的,並分別設定任務限額。當 Dispatch center接收到計算節點的 fetch job 請求時,排程執行緒先從多個使用者佇列中,選出已使用限額比例(比較簡單的演算法模型可以是,已排程任務數量/使用者總限額)最小的使用者佇列,然後從佇列頭部取出一個符合該計算節點條件的子任務返回。子任務排程和普通任務排程在排程優先順序、節點選擇上有所不同,需要單獨設計,這裡我們簡單介紹一下。
-
子任務優先順序
子任務不需要在各自使用者佇列裡重新排隊,子任務排程的目標是希望可以第一時間被排程到。該父任務其實已經被排程到了,而系統處於加快該任務執行的目的,在系統設計上將其再次派發,如果還要和其他未被排程的任務一起競爭,那對這個任務來說是不公平的,也減弱了加速的作用。所以針對分片子任務,會將其放置到一個全域性高優先順序佇列,優先被選擇排程。
-
子任務排程節點選擇
影響到子任務排程節點主要有以下因素:
- 機器型別
機器型別分為硬體轉碼機器與普通轉碼機器,由於兩個環境中使用的編碼器不一樣,所以可能導致合併分片後的視訊會有瑕疵,因此我們選擇將子任務排程到與父任務相同的機器型別。
- 程式碼版本
不同版本的程式碼可能導致轉出的分片無法很好的合併在一起,所以當出現這樣的版本迭代後,可以通過計算節點 worker 上的程式碼版本,來確定子任務能排程到哪些其他計算節點上。
- 資料儲存
當父 worker 上的任務併發大時,就會同時進行多個上傳下載的網路傳輸,這樣會導致分片檔案 IO 階段耗時增加,因此優先選擇將子任務放在父 worker 上執行,就會節省網路 IO 與上傳下載耗時。
掉隊者問題
在分片轉碼場景中,掉隊者問題(straggler problems) 是指在多個子任務中,如果大部分子任務已執行完成,但還剩少數子任務遲遲未完成,父 worker 久久無法進入到下一個流程,從而導致該任務被阻塞住。這在分散式系統中是一種較為常見的現象,針對該問題的系統領域研究論文也是屢見不鮮。
對這個問題的解決方案很大程度會影響系統的效率。如果父 worker 選擇一直等待子任務,就可能出現任務過長時間的等待,這違背了我們提速的初衷。因此,基於保證該任務在有限時間內能被完成的原則,有以下幾個優化方向:
1.冗餘排程
這個方案參考了 Hadoop 中 MapReduce 對掉隊者問題的解決方案:當達到超時標準時,子任務還未完成,則父 worker 會針對同一個分片檔案再次傳送一個新 Tsak 子任務給 Dispatch center,讓其重新排程,並重新執行。當有其中一個子任務完成則取消另一個。
這種做法是用空間換時間,不把希望只放在一個節點上,而是採取賽馬機制。但是,當這樣的情況發生較多時,則會產生大量的任務冗餘,而且也不能保證新起的子任務不阻塞。
2.父 worker 接替完成
為了解決冗餘排程中的不足之處,我們對其進行了優化。當達到超時標準,而子任務還未完成時,則父 worker 會挑選完成進度最少的分片進行轉碼。同樣,其中一個任務完成則取消另一個冗餘的任務。若還有子任務未完成,則繼續挑選,自己完成轉碼,直到所有子任務完成為止。
上述第二種方案較第一種方案的區別在於冗餘任務不會重新排程到其他 worker 上執行,而是優先讓父 worker 來冗餘執行。這樣,父 worker 上會持續對分片進行轉碼,直到整個 job 完全完成。最大的優點是:在不會無限制的消耗資源下,保證父 worker 不會處於無限等待狀態中,只有在少數情況下,當父 worker 負載較高時,會考慮使用其他擁有空閒資源的 worker。
子任務進度跟蹤
在父 worker 挑選子任務執行時,需要收集子任務的進度後選擇進度最慢的子任務進行冗餘執行。在計算任務進度時,我們將一次轉碼分為這四個階段:等待排程、下載與準備、轉碼計算執行、上傳與收尾。
不同階段的開始,表示到達不同的進度:
等待排程0% → 下載與準備20% → 轉碼計算執行30% → 上傳與收尾90% → 結束100%
其中,轉碼計算執行佔70%,也是執行速度無法保證的一個階段,所以需要詳細計算進度,轉碼執行流會定期輸出 metric 日誌,並進行監控計算,當前轉碼進度 = 已轉碼時長(time 欄位)/ 需轉碼時長 。
HLS/DASH 封裝
HLS 格式與其他封裝格式不同之處在於其會有多個 ts 檔案與 m3u8 檔案,對轉出 HLS 視訊的任務進行分片轉碼,會增加分片視訊傳輸與管理的複雜性。因此我們對此問題的解決方案是先將源視訊轉成 mp4 視訊,然後在父 Worker 上合併後,再對整個視訊轉換 HLS 封裝。
測試資料
通過記錄並對比同一個視訊轉為不同解析度視訊的速率,我們可以發現各個單個的優化措施對轉碼速度都有不同程度的提升。在實際線上場景,我們通常會根據使用者設定、視訊屬性決定綜合使用某幾項優化方式。
測試視訊1屬性:
Duration: 00:47:19.21, bitrate: 6087 kb/s
Stream #0:0: Video: h264 (High), yuv420p, 2160x1216, 5951 kb/s, 30 fps
Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 127 kb/s
測試視訊2屬性:
Duration: 02:00:00.86,bitrate: 4388 kb/s
Stream #0:0: Video: h264 (High), yuvj420p, 1920x1080, 4257 kb/s, 25 fps
Stream #0:1: Audio: aac (LC), 48000 Hz, stereo, fltp, 125 kb/s
結語
以上就是本文的全部內容,網易雲信轉碼團隊主要通過排程優化、硬體能力、自研編碼、分片轉碼等維度切入,提升視訊轉碼速度,測試結果顯示轉碼提速效果顯著。另外著重介紹了雲信轉碼系統中對分片轉碼模組的主要設計。我們也會持續進行技術探索,實現提速以及更多的場景覆蓋。後續的系列文章中,我們還會對叢集資源排程演算法、硬體轉碼實踐等其他方面的內容進行分享,也歡迎持續關注我們。
作者介紹
羅微恆,網易雲信高階服務端開發工程師,碩士畢業於武漢大學計算機學院,網易雲信轉碼團隊核心成員,目前負責雲信媒體任務處理系統設計與開發工作,致力於提升雲信視訊轉碼服務質量。
- 資訊|WebRTC M93 更新
- 技術實踐|網易雲信 IM SDK 服務高可用技術方案
- 久等了!【Innovation 2021】網易應用創新開發者大賽正式開賽!
- 用程式碼,打造創意新世界!【Innovation 2021】網易應用創新開發者大賽正式開賽!
- Web端實現RTC視訊特效的解決方案
- 從0搭建線上聊天室,只需4步!
- JavaScript 之事件迴圈(Event Loop)
- C 20 四大特性之一:Module 特性詳解
- Android Flutter 多例項實踐
- 技術實踐 | 網易雲信視訊轉碼提速之分片轉碼
- 網易雲信線上萬人連麥技術大揭祕
- 視訊 QoE 的平衡之道—揭祕網易雲信 NERTC 視訊質量控制系統
- 使用 VideoToolbox 探索低延遲視訊編碼 | WWDC 演講實錄
- 技術實踐 | 如何基於 Flink 實現通用的聚合指標計算框架
- 網易雲信大規模聊天室系統架構解析
- 探尋使用者自定義定時任務的實踐方案
- 如何在 Electron 上實現 IM SDK 聊天訊息全文檢索
- 架構解析|網易自研新一代大規模分散式傳輸網
- 直播點播窄帶高清之 JND 感知編碼技術
- Flutter 混合開發基礎