量化視訊封裝的成本
不必要的封裝資訊佔用了可觀的空間,如果能優化這些封裝資訊,就能進一步壓縮視訊,提升使用者的觀看體驗。本文來自Mux科技部落格,LiveVideoStack對原文進行了摘譯。
文 / MatthewSzatmary
譯 / John
原文:
https://mux.com/blog/quantifying-packaging-overhead-2/
Mux可使您就像呼叫單個API一樣輕鬆在您的應用或網站上新增視訊,實現這種簡易操作需要多項可分析視訊內容並將其轉換為具有出色播放相容性的媒體檔案或資料流的處理步驟,這些步驟一般都十分繁瑣且龐大,我們將其按一定順序組成的集合稱為媒體處理流程。
處理流程主要是對每個音訊或視訊幀執行的一系列資料分析或轉換。不同階段對應不同的幀處理步驟,某一階段步驟結束之後下一階段步驟被執行操作,多步驟所組成的簡化處理流程如下圖所示:
這些步驟中的每一個都值得深度發掘,但今天我們主要關注處理流程中經常被忽視的一項——封裝。
封裝器的主要工作是獲取音訊和視訊編碼器的輸出並插入如果按照正確速率播放媒體所需的時間戳與信令等資訊,同時還要確保音訊與視訊的同步性。最終得到被封裝在“容器”中的檔案或流並允許播放器成功開啟與訪問資料,如mp4或HLS格式檔案。
幾年前,Apple在HLS中添加了對分片mp4檔案的支援,但並非所有裝置都能獲得這一新特性。因此,大多數流仍然使用較舊的傳輸流(通常稱為TS)格式。TS似乎是一種令人費解的格式,但對於廣播或有線電視領域的從業者來說這種格式無處不在。而無處不在也意味著硬體解碼器普遍對TS有良好的相容性與支援,如果讓我推測,這也就是為什麼Apple在第一代iPhone中普遍選擇TS而非HLS,以及為什麼TS在今天仍然非常普遍。
TS有一些不同尋常的特性。由於其本質上是為乙太網之前的世界構建,包括丟失、亂序資料封裝檢測以及遠端時間同步等數字無線廣播必需的功能在網際網路上僅需藉助TCP與每個裝置中的高精度時鐘之間的協作即可處理;除此之外,TS還使用188位元組的固定封裝大小,每個封裝包以同步位元組開始,以便於識別初始封裝。(這種設計如果用於在隨機位置加入多條播放的資料流,即可獲得良好效果,例如切換電視訊道時;但就像HLS的情況一樣,這對於通過HTTP拉取資料流並以檔案形式儲存視訊的網際網路視訊傳輸來說並非必需。而不使用這些功能的缺陷就是儲存空間被白白佔用。對於具有高位元速率的檔案而言這不是問題,但對處於低頻寬環境中的服務來說,卻意味著高昂的成本。
每個188位元組的TS包具有4位元組的標頭(header)。該標頭包含同步位元組、一部分標誌位、封裝的ID(或具有唯一標識的音訊或視訊流 PID)以及連續性計數器(用於識別丟失或無序的包)。然後每個幀都有一個前置的Packetised基本流(PES)標頭。PES標頭最少為14個位元組(如果幀解碼時間與呈現時間不匹配,則為19個位元組,即B幀),並會對幀時間戳進行編碼等。因此,第一個資料包最多可用170個位元組,而後續資料封裝包有184個位元組可用。如果幀少於170個位元組,則必須對其進行填充以使用完整資料包。如果幀是171位元組,則需要第二個資料封裝包,因此需要376個位元組(188x2)來傳輸171個位元組的有效負載,這會將所需頻寬增加一倍以上。實際上,170位元組以下的幀並不常見。但是,在1Mbps以下的位元率下,10%或更多的(Overhead)開銷並不罕見。
一個現實世界的例子
我們拍攝了一段測試視訊,使用以下命令通過FFmpeg將其編碼為HLS:
ffmpeg -i tears_of_steel_720p.mp4 -vcodec libx264 -preset faster -x264opts keyint=120:min-keyint=120:scenecut=-1 -b:v 500k -b:a 96k -hls_playlist_type vod ffmpeg/ffmpeg.m3u8
最終組合流大小為58196152位元組,封裝開銷(overhead)為6.24%。考慮到2.13%(184/188)是理論上的最小值且折扣PES標題和填充,實際表現並沒有那麼糟糕。
但我們能做得更好嗎?如果可以,我們希望節省的位元速率可用於降低緩衝以改善視訊質量繼而改善使用者體驗。但任改善實踐的第一步是確定如何衡量封裝開銷。已註冊的Apple開發人員可以訪問HTTP Live Streaming Tools等工具,這些工具存在兩個問題:第一是僅支援MacOS,第二是最新版本似乎不再顯示封裝開銷。為了解決這個問題,我們開源了我們的muxincstreamvalidator 工具(https://github.com/muxinc/hlstools)。儘管在編寫初期,此工具僅報告封裝開銷,但其後續版本中可能會擴充套件更多功能。以上是用於衡量FFmpeg封裝開銷的工具。
為減少封裝開銷,我們可以利用編碼媒體碼流的一些屬性。大多數音訊編解碼器使用固定的取樣率和per-frame的取樣數進行編碼。AAC音訊則固定每幀使用1024個樣本。因此,在48000Khz時,每幀持續21⅓毫秒。因為幀持續時間可以由解碼器確定而其中不包含來自PES幀頭的時間戳,所以我們可以為每個PES標頭打包多於一個的音訊幀,從而減少PES開銷與最小化幀的最終TS分組所需的填充。但是,這裡的視訊幀中並沒有可匯出的時間戳,因此打包不起作用。MPEG視訊編解碼器確實包含用於識別每個幀的第一個位元組,被稱為起始碼的特定位元序列。因此,解碼器不需要容器傳送訊號以通知每幀開始時流中的確切位置。當有一個小於184位元組的最終有效載荷需要填充時,我們可以截斷那些額外的位元組,採用零填充策略並將位元組前進到下一幀。不幸的是,對於170位元組以下的視訊幀,我們仍然無法做到這一點。
Mux的程式碼轉換器使用但不限於使用這些技術以將開銷降至最低。我們將相同的 tears_of_steel_720p.mp4 視訊攝取到Mux的muxincstreamvalidator工具中並測量其開銷。
傳輸流包含4個PID,其中PID 0始終是程式關聯表(PAT),其編碼節目對映表(PMT)的PID在這種情況下為4096;PMT對音訊(257)和視訊(256)流的PID進行編碼,由於不包含媒體只包含元資料,PAT和PMT的開銷為100%。最終流為55330092位元組,開銷為3.32%。理論最小值更接近2.12%。
為了確保這是一個同類比較,我們使用FFmpeg重新混合Mux編碼流並測量結果。
ffmpeg -i ./mux/manifest.m3u8 -codec copy -hls_playlist_type vod remux/remux.m3u8
FFmpeg包含一個額外的“服務”PID(17),除了額外1713244位元組的開銷,其他看上去差別不大類似。
我們嘗試了一項實驗,通過增加既定百分比的位元速率生成相似且效率較低但視訊質量得到明顯改善的封裝檔案,最終結果的VMAF評分低於3分,我們可以認為這改善了視覺質量。因此,通過節省一部分處理來改善網路環境較差的網路邊緣地區使用者的產品使用體驗似乎是一項不錯的選擇。
LiveVideoStack 招募
LiveVideoStack正在招募編輯/記者/運營,與全球頂尖多媒及技術專家和LiveVideoStack年輕的夥伴一起,推動多媒體技術生態發展。瞭解崗位資訊請在BOSS直聘上搜索“LiveVideoStack”,或通過微信“Tony_Bao_”與主編包研交流。同時,我們也歡迎通過業餘時間向LiveVideoStack貢獻內容。
LiveVideoStackCon2019北京正在招募講師,點選【閱讀原文】瞭解詳細資訊。