1. 程式人生 > >【移動開發】關於一對一視訊交友技術原始碼(六)現代播放器原理

【移動開發】關於一對一視訊交友技術原始碼(六)現代播放器原理

在上一篇延遲優化中,我們分享了不少簡單實用的調優技巧。本篇是《一對一視訊直播技術詳解》系列之六:現代播放器原理。

近年來,多平臺適配需求的增長導致了流媒體自適應位元速率播放的興起,這迫使 Web 和移動開發者們必須重新思考視訊技術的相關邏輯。首先,巨頭們分分發布了 HLS、HDS 和 Smooth Streaming 等協議,把所有相關細節都隱藏在它們專供的 SDK 中。開發者們沒法自由的修改播放器中的多媒體引擎等邏輯:你沒法修改自適應位元速率的規則和快取大小,甚至是你切片的長度。這些播放器可能用起來簡單,但是你沒有太多去定製它的選擇,即便是糟糕的功能也只能忍受。

但是隨著不同應用場景的增加,可定製化功能的需求越來越強。僅僅是直播和點播之間,就存在不同的 buffer 管理、ABR 策略和快取策略等方面的差別。這些需求催生了一系列更為底層關於多媒體操作 API 的誕生:Flash 上面的 Netstream,HTML5 上的 Media Source Extensions,以及 Android 上的 Media Codec,同時業界又出現了一個基於 HTTP 的標準流格式 MPEG-DASH。這些更高階的能力為開發者提供了更好的靈活性,讓他們可以構建適合自己業務需求的播放器和多媒體引擎。

今天我們來分享一下如何構建一個現代播放器,以及構建這樣一個播放器需要哪些關鍵元件。通常來說,一個典型的播放器可以分解成三部分:UI、 多媒體引擎和解碼器,如圖 1 所示:

圖 1. 現代播放器架構

使用者介面(UI):這是播放器最上層的部分。它通過三部分不同的功能特性定義了終端使用者的觀看體驗:面板(播放器的外觀設計)、UI(所有可自定義的特性如播放列表和社交分享等)以及業務邏輯部分(特定的業務邏輯特性如廣告、裝置相容性邏輯以及認證管理等)。

多媒體引擎:這裡處理所有播放控制相關的邏輯,如描述檔案的解析,視訊片段的拉取,以及自適應位元速率規則的設定和切換等等,我們將在下文中詳細講解這部分內容。由於這些引擎一般和平臺繫結的比較緊,因此可能需要使用多種不同的引擎才能覆蓋所有平臺。

解碼器和 DRM 管理器:播放器最底層的部分是解碼器和 DRM 管理器,這層的功能直接呼叫作業系統暴露出來的 API。解碼器的主要功能在於解碼並渲染視訊內容,而 DRM 管理器則通過解密過程來控制是否有權播放。

接下來我們將使用例子來介紹各層所扮演的不同角色。

一、使用者介面(UI)

UI 層是播放器的最上層,它控制了你使用者所能看到和互動的東西,同時也可以使用你自己的品牌來將其定製,為你的使用者提供獨特的使用者體驗。這一層最接近於我們說的前端開發部分。在 UI 內部,我們也包含了業務邏輯元件,這些元件構成了你播放體驗的獨特性,雖然終端使用者沒法直接和這部分功能進行互動。

UI 部分主要包含三大元件:

1. 面板

面板是對播放器視覺相關部分的統稱:進度控制條、按鈕和動畫圖示等等,如圖 2 所示。和大部分設計類的元件一樣,這部分元件也是使用 CSS 來實現的,設計師或者開發者可以很方便的拿來整合(即便你使用的是 JW Player 和 Bitdash 這種整套解決方案)。

圖 2. 播放器面板

2. UI 邏輯

UI 邏輯部分定義了播放過程中和使用者互動方面所有可見的互動:播放列表、縮圖、播放頻道的選擇以及社交媒體分享等。基於你預期達到的播放體驗,還可以往這部分中加入很多其它的功能特性,其中有很多以外掛的形式存在了,或許可以從中找到一些靈感:https://github.com/videojs/video.js/wiki/Plugins#community-pluginsUI 邏輯部分包含的功能較多,我們不一一詳細介紹,直接以 Eurosport 播放器的 UI 來作為例子直觀感受一下這些功能。

圖 3. Eurosport 播放器的使用者介面

從圖 3 可以看出,除了傳統的 UI 元素之外,還有一個非常有趣的特性,在使用者觀看 DVR 流媒體的時候,直播以小視窗的形式展示,觀眾可以通過這個小視窗隨時回到直播中。由於佈局或者 UI 和多媒體引擎完全獨立,這些特性在 HTML5 中使用 dash.js 只需要幾行程式碼就能實現。對於 UI 部分來說,最好的實現方式是讓各種特性都以外掛/模組的形式新增到 UI 核心模組中。

3. 業務邏輯

除了上面兩部分「可見」的功能特性之外,還有一個不可見的部分,這部分構成了你業務的獨特性:認證和支付、頻道和播放列表的獲取,以及廣告等。這裡也包含一些技術相關的東西,比如用於 A/B 測試模組,以及和裝置相關的配置,這些配置用於在多種不同型別的裝置之間選擇多個不同的媒體引擎。

為了揭開底層隱藏的複雜性,我們在這裡更詳細的講解一下這些模組:

裝置檢測與配置邏輯:這是最重要的特性之一,因為它將播放和渲染剝離開來了。例如,基於你瀏覽器的不同版本,播放器可能會自動為你選擇一個基於 HTML5 MSE 的多媒體引擎 hls.js,或者為你選擇一個基於 flash 的播放引擎 FlasHls 來播放 HLS 視訊流。這部分的最大特點在於,無論你使用什麼樣的底層引擎,在上層都可以使用相同的 Java 或者 CSS 來定製你的 UI 或者業務邏輯。

能夠檢測使用者裝置的能力允許你按需配置終端使用者的體驗:如果是在移動裝置而非 4K 螢幕裝置上播放,你可能需要從一個較低的位元速率開始。

A/B 測試邏輯:A/B 測試是為了能夠在生產環節中灰度部分使用者。例如,你可能會給部分 Chrome 使用者提供一個新的按鈕或者新的多媒體引擎,並且還能保證它所有的工作都正常如期進行。

廣告(可選):在客戶端處理廣告是最複雜的業務邏輯之一。如 videojs-contrib-ads 這個外掛模組的流程圖給出一樣,插入廣告的流程中包含多個步驟。對於 HTTP 視訊流來說,你或多或少會用到一些已有的格式如 VAST、VPAID 或者 Google IMA,它們能夠幫你從廣告伺服器中拉取視訊廣告(通常是過時的非自適應格式),放在視訊的前期、中期和後期進行播放,且不可跳過。

總結:

針對你的定製化需求,你可能選擇使用包含所有經典功能的 JW Player 來播放(它也允許你定製部分功能),或者基於 Videojs 這樣的開源播放器來定製你自己的功能特性。甚至為了在瀏覽器和原生播放器之間統一使用者體驗,你也可以考慮使用 React Native 來進行 UI 或者面板的開發,使用 Haxe 來進行業務邏輯的開發,這些優秀的庫都可以在多種不同型別的裝置之間共用同一套程式碼庫。

圖 4. 業務邏輯流程圖

二、多媒體引擎

近年來,多媒體引擎更是以一種全新獨立的元件出現在播放器架構中。在 MP4 時代,平臺處理了所有播放相關的邏輯,而只將一部分多媒體處理相關的特性(僅僅是播放、暫停、拖拽和全屏模式等功能)開放給開發者。

然而,新的基於 HTTP 的流媒體格式需要一種全新的元件來處理和控制新的複雜性:解析宣告檔案、下載視訊片段、自適應位元速率監控以及決策指定等等甚至更多。起初,ABR 的複雜性被平臺或者裝置提供商處理了。然而,隨著主播控制和定製播放器需求的遞增,一些新的播放器中慢慢也開放了一些更為底層的 API(如 Web 上的 Media Source Extensons,Flash 上的 Netstream 以及 Android 平臺的 Media Codec),並迅速吸引來了很多基於這些底層 API 的強大而健壯的多媒體引擎。

圖 5. Google 提供的多媒體處理引擎 Shakaplayer 的資料流程圖

接下來我們將詳細講解現代多媒體處理引擎中各元件的細節:

1. 宣告檔案解釋和解析器

在基於 HTTP 的視訊流中,一切都是以一個描述檔案開始。該宣告檔案包含了媒體伺服器所需理解的元資訊:有多少種不同型別的視訊質量、語言以及字母等,它們分別是什麼。解析器從 XML 檔案(對於 HLS 來說則是一種特殊的 m3u8 檔案)中取得描述資訊,然後從這些資訊中取得正確的視訊資訊。當然,媒體伺服器的型別很多,並不是所有都正確的實現了規範,因此解析器可能需要處理一些額外的實現錯誤。

一旦提取了視訊資訊,解析器則會從中解析出資料,用於構建流式的視覺影象,同時知道如何獲取不同的視訊片段。在某些多媒體引擎中,這些視覺影象先以一副抽象多媒體圖的形式出現,然後在螢幕上繪製出不同 HTTP 視訊流格式的差異特徵。

在直播流場景中,解析器也必須週期性的重新獲取宣告檔案,以便獲得最新的視訊片段資訊。

2. 下載器(下載宣告檔案、多媒體片段以及金鑰)

下載器是一個包裝了處理 HTTP 請求原生 API 的模組。它不僅用於下載多媒體檔案,在必要的時候也可以用於下載宣告檔案和 DRM 金鑰。下載器在處理網路錯誤和重試方面扮演著非常重要的角色,同時能夠收集當前可用頻寬的資料。

注意:下載多媒體檔案可能使用 HTTP 協議,也可能使用別的協議,如點對點實時通訊場景中的 WebRTC 協議。

3. 流播放引擎

流播放引擎是和解碼器 API 互動的中央模組,它將不同的多媒體片段匯入編碼器,同時處理多位元速率切換和播放時的差異性(如宣告檔案和視訊切片的差異,以及卡頓時的自動跳幀)。

4. 資源質量引數預估器(頻寬、CPU 和幀率等)

預估器從各種不同的維度獲取資料(塊大小,每片段下載時間,以及跳幀數),並將其匯聚起來用於估算使用者可用的頻寬和 CPU 計算能力。這是輸出用於 ABR (Adaptive Bitrate, 自適應位元速率)切換控制器做判斷。

5. ABR 切換控制器

ABR 切換器可能是多媒體引擎中最為關鍵的部分——通常也是大家最為忽視的部分。該控制器讀取預估器輸出的資料(頻寬和跳幀數),使用自定義演算法根據這些資料做出判斷,告訴流播放引擎是否需要切換視訊或者音訊質量。該領域有很多研究性的工作,其中最大的難點在於在再緩衝風險和切換頻率(太頻繁的切換可能導致糟糕的使用者體驗)之間找到平衡。

6. DRM 管理器(可選元件)

今天所有的付費視訊服務都基於 DRM 管理,而 DRM 則很大程度上依賴於平臺或者裝置,我們將在後續講解播放器的時候看到。多媒體引擎中的 DRM 管理器是更底層解碼器中內容解密 API 的包裝。只要有可能,它會盡量通過抽象的方式來遮蔽瀏覽器或者作業系統實現細節的差異性。該元件通常和流處理引擎緊密連線在一起,因為它經常和解碼器層互動。

7. 格式轉換複用器(可選元件)

後文中我們將看到,每個平臺在封包和編碼方面都有它的侷限性(Flash 讀的是 FLV 容器封裝的 H.264/AAC 檔案,MSE 讀的是 ISOBMFF 容器封裝的 H.264/AAC 檔案)。這就導致了有些視訊片段在解碼之前需要進行格式轉換。例如,有了 MPEG2-TS 到 ISOBMFF 的格式轉換複用器之後,hls.js 就能使用 MSE 格式的內容來播放 HLS 視訊流。多媒體引擎層面的格式轉換複用器曾經遭受質疑;然而,隨著現代 Java 或者 Flash 解釋權效能的提升,它帶來的效能損耗幾乎可以忽略不計,對使用者體驗也不會造成多大的影響。

** 總結**

多媒體引擎中也有非常多的不同元件和特性,從字幕到截圖到廣告插入等等。接下來我們也會單獨寫一篇文章來對比多種不同引擎的差異,通過一些測試和市場資料來為引擎的選擇給出一些實質性的指導。值得注意的是,要構建一個相容各平臺的播放器,提供多個可自由替換的多媒體引擎是非常重要的,因為底層解碼器是和使用者平臺相關的,接下來我們將重點講解這方面的內容。

三、解碼器和 DRM 管理器

出於解碼效能(解碼器)和安全考慮(DRM),解碼器和 DRM 管理器與作業系統平臺密切繫結。

圖 6. 解碼器、渲染器和 DRM 工作流程圖

1. 解碼器

解碼器處理最底層播放相關的邏輯。它將不同封裝格式的視訊進行解包,並將其內容解碼,然後將解碼後的視訊幀交給作業系統進行渲染,最終讓終端使用者看到。

由於視訊壓縮演算法變得越來越複雜,解碼過程是一個需要密集計算的過程,並且為了保證解碼效能和流暢的播放體驗,解碼過程需要強依賴於作業系統和硬體。現在的大部分解碼都依賴於 GPU 加速解碼的幫助(這也是為什麼免費而更強大的 VP9 解碼器沒有贏得 H.264 市場地位的原因之一)。如果沒有 GPU 的加速,解碼一個 1080P 的視訊就會佔去 70% 左右的 CPU 計算量,並且丟幀率還可能很嚴重。

在解碼和渲染視訊幀的基礎之上,管理器也提供了一個原生的 buffer,多媒體引擎可以直接與該 buffer 進行互動,實時瞭解它的大小並在必要的時候重新整理它。

我們前面提到,每個平臺都有它自己的渲染引擎和相應的 API:Flash 平臺有 Netstream,Android 平臺有 Media Codec API,而 Web 上則有標準的 Media Sources Extensions。MSE 越來越吸引眼球,將來可能會成為繼瀏覽器之後其它平臺上的事實標準。

2. DRM 管理器

圖 7. DRM 管理器

今天,在傳輸工作室生產的付費內容的時候,DRM 是必要的。這些內容必須防止被盜,因此 DRM 的程式碼和工作過程都向終端使用者和開發者遮蔽了。解密過的內容不會離開解碼層,因此也不會被攔截。

為了標準化 DRM 以及為各平臺的實現提供一定的互通性,幾個 Web 巨頭一起建立了通用加密標準Common Encryption (CENC) 和通用的多媒體加密擴充套件Encrypted Media Extensions,以便為多個 DRM 提供商(例如,EME 可用於 Edge 平臺上的 Playready 和 Chrome 平臺上的 Widewine)構建一套通用的 API,這些 API 能夠從 DRM 授權模組讀取視訊內容加密金鑰用於解密。

CENC 聲明瞭一套標準的加密和金鑰對映方法,它可用於在多個 DRM 系統上解密相同的內容,只需要提供相同的金鑰即可。

在瀏覽器內部,基於視訊內容的元資訊,EME 可以通過識別它使用了哪個 DRM 系統加密,並呼叫相應的解密模組(Content Decryption Module, CDM)解密 CENC 加密過的內容。解密模組 CDM 則會去處理內容授權相關的工作,獲得金鑰並解密視訊內容。

CENC 沒有規定授權的發放、授權的格式、授權的儲存、以及使用規則和許可權的對映關係等細節,這些細節的處理都由 DRM 提供商負責。

四、總結

今天我們深入瞭解了一下視訊播放器三個層面的不同內容,這個現代播放器結構最優秀之處在於其互動部分完全和多媒體引擎邏輯部分分離,讓主播可以無縫而自由靈活的定製終端使用者體驗,同時在多種不同終端裝置上使用不同的多媒體引擎還能保證順利播放多種不同格式的視訊內容。

在 Web 平臺,得益於多媒體引擎如 dash.js、Shaka Player 和 hls.js 這些趨於成熟庫的幫助, MSE 和 EME 正在成為播放的新標準,同時也越來越多有影響力的廠家使用這些播放引擎。近年來,注意力也開始伸向機頂盒和網際網路電視,我們也看到越來越多這樣的新裝置使用 MSE 來作為其底層多媒體處理引擎。我們也將持續投入更多的力量去支援這些標準。