《視頻直播技術(shù)詳解》系列之現(xiàn)代播放器原理
近年來,多平臺(tái)適配需求的增長導(dǎo)致了流媒體自適應(yīng)碼率播放的興起,這迫使 Web 和移動(dòng)開發(fā)者們必須重新思考視頻技術(shù)的相關(guān)邏輯。首先,巨頭們分分發(fā)布了 HLS、HDS 和 Smooth Streaming 等協(xié)議,把所有相關(guān)細(xì)節(jié)都隱藏在它們專供的 SDK 中。開發(fā)者們沒法自由的修改播放器中的多媒體引擎等邏輯:你沒法修改自適應(yīng)碼率的規(guī)則和緩存大小,甚至是你切片的長度。這些播放器可能用起來簡單,但是你沒有太多去定制它的選擇,即便是糟糕的功能也只能忍受。
但是隨著不同應(yīng)用場(chǎng)景的增加,可定制化功能的需求越來越強(qiáng)。僅僅是直播和點(diǎn)播之間,就存在不同的 buffer 管理、ABR 策略和緩存策略等方面的差別。這些需求催生了一系列更為底層關(guān)于多媒體操作 API 的誕生:Flash 上面的 Netstream,HTML5 上的 Media Source Extensions,以及 Android 上的 Media Codec,同時(shí)業(yè)界又出現(xiàn)了一個(gè)基于 HTTP 的標(biāo)準(zhǔn)流格式 MPEG-DASH。這些更高級(jí)的能力為開發(fā)者提供了更好的靈活性,讓他們可以構(gòu)建適合自己業(yè)務(wù)需求的播放器和多媒體引擎。
今天我們來分享一下如何構(gòu)建一個(gè)現(xiàn)代播放器,以及構(gòu)建這樣一個(gè)播放器需要哪些關(guān)鍵組件。通常來說,一個(gè)典型的播放器可以分解成三部分:UI、 多媒體引擎和解碼器,如圖 1 所示:
圖 1. 現(xiàn)代播放器架構(gòu)
用戶界面(UI):這是播放器最上層的部分。它通過三部分不同的功能特性定義了終端用戶的觀看體驗(yàn):皮膚(播放器的外觀設(shè)計(jì))、UI(所有可自定義的特性如播放列表和社交分享等)以及業(yè)務(wù)邏輯部分(特定的業(yè)務(wù)邏輯特性如廣告、設(shè)備兼容性邏輯以及認(rèn)證管理等)。多媒體引擎:這里處理所有播放控制相關(guān)的邏輯,如描述文件的解析,視頻片段的拉取,以及自適應(yīng)碼率規(guī)則的設(shè)定和切換等等,我們將在下文中詳細(xì)講解這部分內(nèi)容。由于這些引擎一般和平臺(tái)綁定的比較緊,因此可能需要使用多種不同的引擎才能覆蓋所有平臺(tái)。解碼器和 DRM 管理器:播放器最底層的部分是解碼器和 DRM 管理器,這層的功能直接調(diào)用操作系統(tǒng)暴露出來的 API。解碼器的主要功能在于解碼并渲染視頻內(nèi)容,而 DRM 管理器則通過解密過程來控制是否有權(quán)播放。
接下來我們將使用例子來介紹各層所扮演的不同角色。
一、用戶界面(UI)
UI 層是播放器的最上層,它控制了你用戶所能看到和交互的東西,同時(shí)也可以使用你自己的品牌來將其定制,為你的用戶提供獨(dú)特的用戶體驗(yàn)。這一層最接近于我們說的前端開發(fā)部分。在 UI 內(nèi)部,我們也包含了業(yè)務(wù)邏輯組件,這些組件構(gòu)成了你播放體驗(yàn)的獨(dú)特性,雖然終端用戶沒法直接和這部分功能進(jìn)行交互。
UI 部分主要包含三大組件:
1. 皮膚
皮膚是對(duì)播放器視覺相關(guān)部分的統(tǒng)稱:進(jìn)度控制條、按鈕和動(dòng)畫圖標(biāo)等等,如圖 2 所示。和大部分設(shè)計(jì)類的組件一樣,這部分組件也是使用 CSS 來實(shí)現(xiàn)的,設(shè)計(jì)師或者開發(fā)者可以很方便的拿來集成(即便你使用的是 JW Player 和 Bitdash 這種整套解決方案)。?
圖 2. 播放器皮膚
2. UI 邏輯
UI 邏輯部分定義了播放過程中和用戶交互方面所有可見的交互:播放列表、縮略圖、播放頻道的選擇以及社交媒體分享等。基于你預(yù)期達(dá)到的播放體驗(yàn),還可以往這部分中加入很多其它的功能特性,其中有很多以插件的形式存在了,或許可以從中找到一些靈感:https://github.com/videojs/video.js/wiki/Plugins#community-plugins
UI 邏輯部分包含的功能較多,我們不一一詳細(xì)介紹,直接以 Eurosport 播放器的 UI 來作為例子直觀感受一下這些功能。
圖 3. Eurosport ?播放器的用戶界面
從圖 3 可以看出,除了傳統(tǒng)的 UI 元素之外,還有一個(gè)非常有趣的特性,在用戶觀看 DVR 流媒體的時(shí)候,直播以小視窗的形式展示,觀眾可以通過這個(gè)小窗口隨時(shí)回到直播中。由于布局或者 UI 和多媒體引擎完全獨(dú)立,這些特性在 HTML5 中使用 dash.js 只需要幾行代碼就能實(shí)現(xiàn)。
對(duì)于 UI 部分來說,最好的實(shí)現(xiàn)方式是讓各種特性都以插件/模塊的形式添加到 UI 核心模塊中。
3. 業(yè)務(wù)邏輯
除了上面兩部分「可見」的功能特性之外,還有一個(gè)不可見的部分,這部分構(gòu)成了你業(yè)務(wù)的獨(dú)特性:認(rèn)證和支付、頻道和播放列表的獲取,以及廣告等。這里也包含一些技術(shù)相關(guān)的東西,比如用于 A/B 測(cè)試模塊,以及和設(shè)備相關(guān)的配置,這些配置用于在多種不同類型的設(shè)備之間選擇多個(gè)不同的媒體引擎。
為了揭開底層隱藏的復(fù)雜性,我們?cè)谶@里更詳細(xì)的講解一下這些模塊:
設(shè)備檢測(cè)與配置邏輯:這是最重要的特性之一,因?yàn)樗鼘⒉シ藕弯秩緞冸x開來了。例如,基于你瀏覽器的不同版本,播放器可能會(huì)自動(dòng)為你選擇一個(gè)基于 HTML5 MSE 的多媒體引擎 hls.js,或者為你選擇一個(gè)基于 flash 的播放引擎 FlasHls 來播放 HLS 視頻流。這部分的最大特點(diǎn)在于,無論你使用什么樣的底層引擎,在上層都可以使用相同的 JavaScript 或者 CSS 來定制你的 UI 或者業(yè)務(wù)邏輯。
能夠檢測(cè)用戶設(shè)備的能力允許你按需配置終端用戶的體驗(yàn):如果是在移動(dòng)設(shè)備而非 4K 屏幕設(shè)備上播放,你可能需要從一個(gè)較低的碼率開始。
A/B 測(cè)試邏輯:A/B 測(cè)試是為了能夠在生產(chǎn)環(huán)節(jié)中灰度部分用戶。例如,你可能會(huì)給部分 Chrome 用戶提供一個(gè)新的按鈕或者新的多媒體引擎,并且還能保證它所有的工作都正常如期進(jìn)行。
廣告(可選):在客戶端處理廣告是最復(fù)雜的業(yè)務(wù)邏輯之一。如 videojs-contrib-ads 這個(gè)插件模塊的流程圖給出一樣,插入廣告的流程中包含多個(gè)步驟。對(duì)于 HTTP 視頻流來說,你或多或少會(huì)用到一些已有的格式如 VAST、VPAID 或者 Google IMA,它們能夠幫你從廣告服務(wù)器中拉取視頻廣告(通常是過時(shí)的非自適應(yīng)格式),放在視頻的前期、中期和后期進(jìn)行播放,且不可跳過。
總結(jié):
針對(duì)你的定制化需求,你可能選擇使用包含所有經(jīng)典功能的 JW Player 來播放(它也允許你定制部分功能),或者基于 Videojs 這樣的開源播放器來定制你自己的功能特性。甚至為了在瀏覽器和原生播放器之間統(tǒng)一用戶體驗(yàn),你也可以考慮使用 React Native 來進(jìn)行 UI 或者皮膚的開發(fā),使用 Haxe 來進(jìn)行業(yè)務(wù)邏輯的開發(fā),這些優(yōu)秀的庫都可以在多種不同類型的設(shè)備之間共用同一套代碼庫。?
圖 4. 業(yè)務(wù)邏輯流程圖
二、多媒體引擎
近年來,多媒體引擎更是以一種全新獨(dú)立的組件出現(xiàn)在播放器架構(gòu)中。在 MP4 時(shí)代,平臺(tái)處理了所有播放相關(guān)的邏輯,而只將一部分多媒體處理相關(guān)的特性(僅僅是播放、暫停、拖拽和全屏模式等功能)開放給開發(fā)者。
然而,新的基于 HTTP 的流媒體格式需要一種全新的組件來處理和控制新的復(fù)雜性:解析聲明文件、下載視頻片段、自適應(yīng)碼率監(jiān)控以及決策指定等等甚至更多。起初,ABR 的復(fù)雜性被平臺(tái)或者設(shè)備提供商處理了。然而,隨著主播控制和定制播放器需求的遞增,一些新的播放器中慢慢也開放了一些更為底層的 API(如 Web 上的 Media Source Extensons,F(xiàn)lash 上的 Netstream 以及 Android 平臺(tái)的 Media Codec),并迅速吸引來了很多基于這些底層 API 的強(qiáng)大而健壯的多媒體引擎。
圖 5. Google 提供的多媒體處理引擎 Shakaplayer 的數(shù)據(jù)流程圖
接下來我們將詳細(xì)講解現(xiàn)代多媒體處理引擎中各組件的細(xì)節(jié):
1. 聲明文件解釋和解析器
在基于 HTTP 的視頻流中,一切都是以一個(gè)描述文件開始。該聲明文件包含了媒體服務(wù)器所需理解的元信息:有多少種不同類型的視頻質(zhì)量、語言以及字母等,它們分別是什么。解析器從 XML 文件(對(duì)于 HLS 來說則是一種特殊的 m3u8 文件)中取得描述信息,然后從這些信息中取得正確的視頻信息。當(dāng)然,媒體服務(wù)器的類型很多,并不是所有都正確的實(shí)現(xiàn)了規(guī)范,因此解析器可能需要處理一些額外的實(shí)現(xiàn)錯(cuò)誤。
一旦提取了視頻信息,解析器則會(huì)從中解析出數(shù)據(jù),用于構(gòu)建流式的視覺圖像,同時(shí)知道如何獲取不同的視頻片段。在某些多媒體引擎中,這些視覺圖像先以一副抽象多媒體圖的形式出現(xiàn),然后在屏幕上繪制出不同 HTTP 視頻流格式的差異特征。
在直播流場(chǎng)景中,解析器也必須周期性的重新獲取聲明文件,以便獲得最新的視頻片段信息。
2. 下載器(下載聲明文件、多媒體片段以及密鑰)
下載器是一個(gè)包裝了處理 HTTP 請(qǐng)求原生 API 的模塊。它不僅用于下載多媒體文件,在必要的時(shí)候也可以用于下載聲明文件和 DRM 密鑰。下載器在處理網(wǎng)絡(luò)錯(cuò)誤和重試方面扮演著非常重要的角色,同時(shí)能夠收集當(dāng)前可用帶寬的數(shù)據(jù)。
注意:下載多媒體文件可能使用 HTTP 協(xié)議,也可能使用別的協(xié)議,如點(diǎn)對(duì)點(diǎn)實(shí)時(shí)通信場(chǎng)景中的 WebRTC 協(xié)議。
3. 流播放引擎
流播放引擎是和解碼器 API 交互的中央模塊,它將不同的多媒體片段導(dǎo)入編碼器,同時(shí)處理多碼率切換和播放時(shí)的差異性(如聲明文件和視頻切片的差異,以及卡頓時(shí)的自動(dòng)跳幀)。
4. 資源質(zhì)量參數(shù)預(yù)估器(帶寬、CPU 和幀率等)
預(yù)估器從各種不同的維度獲取數(shù)據(jù)(塊大小,每片段下載時(shí)間,以及跳幀數(shù)),并將其匯聚起來用于估算用戶可用的帶寬和 CPU 計(jì)算能力。這是輸出用于 ABR (Adaptive Bitrate, 自適應(yīng)碼率)切換控制器做判斷。
5. ABR 切換控制器
ABR 切換器可能是多媒體引擎中最為關(guān)鍵的部分——通常也是大家最為忽視的部分。該控制器讀取預(yù)估器輸出的數(shù)據(jù)(帶寬和跳幀數(shù)),使用自定義算法根據(jù)這些數(shù)據(jù)做出判斷,告訴流播放引擎是否需要切換視頻或者音頻質(zhì)量。
該領(lǐng)域有很多研究性的工作,其中最大的難點(diǎn)在于在再緩沖風(fēng)險(xiǎn)和切換頻率(太頻繁的切換可能導(dǎo)致糟糕的用戶體驗(yàn))之間找到平衡。
6. DRM 管理器(可選組件)
今天所有的付費(fèi)視頻服務(wù)都基于 DRM 管理,而 DRM 則很大程度上依賴于平臺(tái)或者設(shè)備,我們將在后續(xù)講解播放器的時(shí)候看到。多媒體引擎中的 DRM 管理器是更底層解碼器中內(nèi)容解密 API 的包裝。
只要有可能,它會(huì)盡量通過抽象的方式來屏蔽瀏覽器或者操作系統(tǒng)實(shí)現(xiàn)細(xì)節(jié)的差異性。該組件通常和流處理引擎緊密連接在一起,因?yàn)樗?jīng)常和解碼器層交互。
7. 格式轉(zhuǎn)換復(fù)用器(可選組件)
后文中我們將看到,每個(gè)平臺(tái)在封包和編碼方面都有它的局限性(Flash 讀的是 FLV 容器封裝的 H.264/AAC 文件,MSE 讀的是 ISOBMFF 容器封裝的 H.264/AAC 文件)。這就導(dǎo)致了有些視頻片段在解碼之前需要進(jìn)行格式轉(zhuǎn)換。例如,有了 MPEG2-TS 到 ISOBMFF 的格式轉(zhuǎn)換復(fù)用器之后,hls.js 就能使用 MSE 格式的內(nèi)容來播放 HLS 視頻流。多媒體引擎層面的格式轉(zhuǎn)換復(fù)用器曾經(jīng)遭受質(zhì)疑;然而,隨著現(xiàn)代 JavaScript 或者 Flash 解釋權(quán)性能的提升,它帶來的性能損耗幾乎可以忽略不計(jì),對(duì)用戶體驗(yàn)也不會(huì)造成多大的影響。
總結(jié)
多媒體引擎中也有非常多的不同組件和特性,從字幕到截圖到廣告插入等等。接下來我們也會(huì)單獨(dú)寫一篇文章來對(duì)比多種不同引擎的差異,通過一些測(cè)試和市場(chǎng)數(shù)據(jù)來為引擎的選擇給出一些實(shí)質(zhì)性的指導(dǎo)。值得注意的是,要構(gòu)建一個(gè)兼容各平臺(tái)的播放器,提供多個(gè)可自由替換的多媒體引擎是非常重要的,因?yàn)榈讓咏獯a器是和用戶平臺(tái)相關(guān)的,接下來我們將重點(diǎn)講解這方面的內(nèi)容。
三、解碼器和 DRM 管理器
出于解碼性能(解碼器)和安全考慮(DRM),解碼器和 DRM 管理器與操作系統(tǒng)平臺(tái)密切綁定。?
圖 6. 解碼器、渲染器和 DRM 工作流程圖
1. 解碼器
解碼器處理最底層播放相關(guān)的邏輯。它將不同封裝格式的視頻進(jìn)行解包,并將其內(nèi)容解碼,然后將解碼后的視頻幀交給操作系統(tǒng)進(jìn)行渲染,最終讓終端用戶看到。
由于視頻壓縮算法變得越來越復(fù)雜,解碼過程是一個(gè)需要密集計(jì)算的過程,并且為了保證解碼性能和流暢的播放體驗(yàn),解碼過程需要強(qiáng)依賴于操作系統(tǒng)和硬件?,F(xiàn)在的大部分解碼都依賴于 GPU 加速解碼的幫助(這也是為什么免費(fèi)而更強(qiáng)大的 VP9 解碼器沒有贏得 H.264 市場(chǎng)地位的原因之一)。如果沒有 GPU 的加速,解碼一個(gè) 1080P 的視頻就會(huì)占去 70% 左右的 CPU 計(jì)算量,并且丟幀率還可能很嚴(yán)重。
在解碼和渲染視頻幀的基礎(chǔ)之上,管理器也提供了一個(gè)原生的 buffer,多媒體引擎可以直接與該 buffer 進(jìn)行交互,實(shí)時(shí)了解它的大小并在必要的時(shí)候刷新它。
我們前面提到,每個(gè)平臺(tái)都有它自己的渲染引擎和相應(yīng)的 API:Flash 平臺(tái)有 Netstream,Android 平臺(tái)有 Media Codec API,而 Web 上則有標(biāo)準(zhǔn)的 Media Sources Extensions。MSE 越來越吸引眼球,將來可能會(huì)成為繼瀏覽器之后其它平臺(tái)上的事實(shí)標(biāo)準(zhǔn)。
2. DRM 管理器
圖 7. DRM 管理器
今天,在傳輸工作室生產(chǎn)的付費(fèi)內(nèi)容的時(shí)候,DRM 是必要的。這些內(nèi)容必須防止被盜,因此 DRM 的代碼和工作過程都向終端用戶和開發(fā)者屏蔽了。解密過的內(nèi)容不會(huì)離開解碼層,因此也不會(huì)被攔截。
為了標(biāo)準(zhǔn)化 DRM 以及為各平臺(tái)的實(shí)現(xiàn)提供一定的互通性,幾個(gè) Web 巨頭一起創(chuàng)建了通用加密標(biāo)準(zhǔn)Common Encryption (CENC)??和通用的多媒體加密擴(kuò)展Encrypted Media Extensions,以便為多個(gè) DRM 提供商(例如,EME 可用于 Edge 平臺(tái)上的 Playready 和 Chrome 平臺(tái)上的 Widewine)構(gòu)建一套通用的 API,這些 API 能夠從 DRM 授權(quán)模塊讀取視頻內(nèi)容加密密鑰用于解密。
CENC 聲明了一套標(biāo)準(zhǔn)的加密和密鑰映射方法,它可用于在多個(gè) DRM 系統(tǒng)上解密相同的內(nèi)容,只需要提供相同的密鑰即可。
在瀏覽器內(nèi)部,基于視頻內(nèi)容的元信息,EME 可以通過識(shí)別它使用了哪個(gè) DRM 系統(tǒng)加密,并調(diào)用相應(yīng)的解密模塊(Content Decryption Module, CDM)解密 CENC 加密過的內(nèi)容。解密模塊 CDM 則會(huì)去處理內(nèi)容授權(quán)相關(guān)的工作,獲得密鑰并解密視頻內(nèi)容。
CENC 沒有規(guī)定授權(quán)的發(fā)放、授權(quán)的格式、授權(quán)的存儲(chǔ)、以及使用規(guī)則和權(quán)限的映射關(guān)系等細(xì)節(jié),這些細(xì)節(jié)的處理都由 DRM 提供商負(fù)責(zé)。
四、總結(jié)
今天我們深入了解了一下視頻播放器三個(gè)層面的不同內(nèi)容,這個(gè)現(xiàn)代播放器結(jié)構(gòu)最優(yōu)秀之處在于其交互部分完全和多媒體引擎邏輯部分分離,讓主播可以無縫而自由靈活的定制終端用戶體驗(yàn),同時(shí)在多種不同終端設(shè)備上使用不同的多媒體引擎還能保證順利播放多種不同格式的視頻內(nèi)容。
在 Web 平臺(tái),得益于多媒體引擎如 dash.js、Shaka Player 和 hls.js 這些趨于成熟庫的幫助, MSE 和 EME 正在成為播放的新標(biāo)準(zhǔn),同時(shí)也越來越多有影響力的廠家使用這些播放引擎。近年來,注意力也開始伸向機(jī)頂盒和互聯(lián)網(wǎng)電視,我們也看到越來越多這樣的新設(shè)備使用 MSE 來作為其底層多媒體處理引擎。我們也將持續(xù)投入更多的力量去支持這些標(biāo)準(zhǔn)。