編輯:關於android開發
關於直播的技術文章不少,成體系的不多。我們將用七篇文章,更系統化地介紹當下大熱的視頻直播各環節的關鍵技術,幫助視頻直播創業者們更全面、深入地了解視頻直播技術,更好地技術選型。
本系列文章大綱如下:
(一)采集
(二)處理
(三)編碼和封裝
(四)推流和傳輸
(五)延遲優化
(六)現代播放器原理
(七)SDK 性能測試模型
在上一篇延遲優化中,我們分享了不少簡單實用的調優技巧。本篇是《視頻直播技術詳解》系列之六:現代播放器原理。
近年來,多平台適配需求的增長導致了流媒體自適應碼率播放的興起,這迫使 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 部分主要包含三大組件:
1. 皮膚
皮膚是對播放器視覺相關部分的統稱:進度控制條、按鈕和動畫圖標等等,如圖 2 所示。和大部分設計類的組件一樣,這部分組件也是使用 CSS 來實現的,設計師或者開發者可以很方便的拿來集成(即便你使用的是 JW Player 和 Bitdash 這種整套解決方案)。
圖 2. 播放器皮膚
2. UI 邏輯
UI 邏輯部分定義了播放過程中和用戶交互方面所有可見的交互:播放列表、縮略圖、播放頻道的選擇以及社交媒體分享等。基於你預期達到的播放體驗,還可以往這部分中加入很多其它的功能特性,其中有很多以插件的形式存在了,或許可以從中找到一些靈感:Plugins · videojs/video.js Wiki · GitHub 邏輯部分包含的功能較多,我們不一一詳細介紹,直接以 Eurosport 播放器的 UI 來作為例子直觀感受一下這些功能。
圖 3. Eurosport 播放器的用戶界面
從圖 3 可以看出,除了傳統的 UI 元素之外,還有一個非常有趣的特性,在用戶觀看 DVR 流媒體的時候,直播以小視窗的形式展示,觀眾可以通過這個小窗口隨時回到直播中。由於布局或者 UI 和多媒體引擎完全獨立,這些特性在 HTML5 中使用 dash.js 只需要幾行代碼就能實現。對於 UI 部分來說,最好的實現方式是讓各種特性都以插件/模塊的形式添加到 UI 核心模塊中。
3. 業務邏輯
除了上面兩部分「可見」的功能特性之外,還有一個不可見的部分,這部分構成了你業務的獨特性:認證和支付、頻道和播放列表的獲取,以及廣告等。這裡也包含一些技術相關的東西,比如用於 A/B 測試模塊,以及和設備相關的配置,這些配置用於在多種不同類型的設備之間選擇多個不同的媒體引擎。
為了揭開底層隱藏的復雜性,我們在這裡更詳細的講解一下這些模塊:
設備檢測與配置邏輯:這是最重要的特性之一,因為它將播放和渲染剝離開來了。例如,基於你浏覽器的不同版本,播放器可能會自動為你選擇一個基於 HTML5 MSE 的多媒體引擎 hls.js,或者為你選擇一個基於 flash 的播放引擎 FlasHls 來播放 HLS 視頻流。這部分的最大特點在於,無論你使用什麼樣的底層引擎,在上層都可以使用相同的 JavaScript 或者 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 視頻流。多媒體引擎層面的格式轉換復用器曾經遭受質疑;然而,隨著現代 JavaScript 或者 Flash 解釋權性能的提升,它帶來的性能損耗幾乎可以忽略不計,對用戶體驗也不會造成多大的影響。
總結
多媒體引擎中也有非常多的不同組件和特性,從字幕到截圖到廣告插入等等。接下來我們也會單獨寫一篇文章來對比多種不同引擎的差異,通過一些測試和市場數據來為引擎的選擇給出一些實質性的指導。值得注意的是,要構建一個兼容各平台的播放器,提供多個可自由替換的多媒體引擎是非常重要的,因為底層解碼器是和用戶平台相關的,接下來我們將重點講解這方面的內容。
出於解碼性能(解碼器)和安全考慮(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 來作為其底層多媒體處理引擎。我們也將持續投入更多的力量去支持這些標准。
本文由七牛雲布道師何李石翻譯自How Modern Video Players Work,原文可去七牛雲官方博客查看。
Android新手入門2016(16)--畫圖 畫圖設計到圖片的格式,有空可以看看圖片資源各種格式。了解一下圖片格式,對學習有用的。而且我面試別人的時候也很喜歡問這個問題
Android SharedPreferences存儲,sharedpreferences一 概念 SharedPreferences存儲方式是Android中存儲輕
我的第一節Android課,第一節Android課 我的第一節安卓課程,今天非比尋常的一天,我開始了我程序猿之路的第一節安卓課程,安卓課程只是我的一個興趣班,我的本專業
Android技巧1:啟動屏+新功能左右導航 前言 很長一段時間沒寫博客了,再不寫點東西真說不過去,把工作上的一些有價值的東西整理出來分享,在當下還有點時效性,不然遲早會