視頻直播技術-視頻-編碼-傳輸-秒開等<轉>


轉載地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=2653547042&idx=1&sn=26d8728548a6b5b657079eeab121e283&scene=21#wechat_redirect

 

現今移動直播技術上的挑戰要遠遠難於傳統設備或電腦直播,其完整的處理環節包括但不限於:音視頻采集、美顏/濾鏡/特效處理、編碼、封包、推流、轉碼、分發、解碼/渲染/播放等。

視頻、直播等基礎知識

 

什么是視頻?

 

首先我們需要理解一個最基本的概念:視頻。從感性的角度來看,視頻就是一部充滿趣味的影片,可以是電影,可以是短片,是一連貫的視覺沖擊力表現豐富的畫面和音頻。但從理性的角度來看,視頻是一種有結構的數據,用工程的語言解釋,我們可以把視頻剖析成如下結構:

 

 

內容元素 ( Content )

  • 圖像 ( Image )

  • 音頻 ( Audio )

  • 元信息 ( Metadata ) 

 

編碼格式 ( Codec )

  • Video : H.264,H.265, …

  • Audio : AAC, HE-AAC, …

 

容器封裝 (Container)

  • MP4,MOV,FLV,RM,RMVB,AVI,…

 

任何一個視頻 Video 文件,從結構上講,都是這樣一種組成方式:

 

  • 由圖像和音頻構成最基本的內容元素;

  • 圖像經過視頻編碼壓縮格式處理(通常是 H.264);

  • 音頻經過音頻編碼壓縮格式處理(例如 AAC);

  • 注明相應的元信息(Metadata);

 

最后經過一遍容器(Container)封裝打包(例如 MP4),構成一個完整的視頻文件。

 

如果覺得難以理解,可以想象成一瓶番茄醬。最外層的瓶子好比這個容器封裝(Container),瓶子上注明的原材料和加工廠地等信息好比元信息(Metadata),瓶蓋打開(解封裝)后,番茄醬本身好比經過壓縮處理過后的編碼內容,番茄和調料加工成番茄醬的過程就好比編碼(Codec),而原材料番茄和調料則好比最原本的內容元素(Content)。

 

視頻編碼壓縮

 

不妨讓我們來深入淺出理解視頻編碼壓縮技術。

 

為了便於視頻內容的存儲和傳輸,通常需要減少視頻內容的體積,也就是需要將原始的內容元素(圖像和音頻)經過壓縮,壓縮算法也簡稱編碼格式。例如視頻里邊的原始圖像數據會采用 H.264 編碼格式進行壓縮,音頻采樣數據會采用 AAC 編碼格式進行壓縮。

 

視頻內容經過編碼壓縮后,確實有利於存儲和傳輸; 不過當要觀看播放時,相應地也需要解碼過程。因此編碼和解碼之間,顯然需要約定一種編碼器和解碼器都可以理解的約定。就視頻圖像編碼和解碼而言,這種約定很簡單:

 

編碼器將多張圖像進行編碼后生產成一段一段的 GOP ( Group of Pictures ) , 解碼器在播放時則是讀取一段一段的 GOP 進行解碼后讀取畫面再渲染顯示。

 

 

GOP ( Group of Pictures ) 是一組連續的畫面,由一張 I 幀和數張 B / P 幀組成,是視頻圖像編碼器和解碼器存取的基本單位,它的排列順序將會一直重復到影像結束。

 

 

I 幀是內部編碼幀(也稱為關鍵幀),P 幀是前向預測幀(前向參考幀),B 幀是雙向內插幀(雙向參考幀)。簡單地講,I 幀是一個完整的畫面,而 P 幀和 B 幀記錄的是相對於 I 幀的變化。

 

如果沒有 I 幀,P 幀和 B 幀就無法解碼。

 

 

小結一下,一個視頻 ( Video ) ,其圖像部分的數據是一組 GOP 的集合, 而單個 GOP 則是一組 I / P / B 幀圖像的集合。

 

在這樣的一種幾何關系中,Video 好比一個 “物體”,GOP 好比 “分子”,I / P / B 幀的圖像則好比 “原子”。

 

想象一下,如果我們把傳輸一個 “物體”,改成傳輸一個一個的 “原子”,將最小顆粒以光速傳送,那么以人的生物肉眼來感知,將是一種怎樣的體驗?

 

什么是視頻直播?

 

不難腦洞大開一下,直播就是這樣的一種體驗。視頻直播技術,就是將視頻內容的最小顆粒 ( I / P / B 幀,…),基於時間序列,以光速進行傳送的一種技術。

 

簡而言之,直播就是將每一幀數據 ( Video / Audio / Data Frame ),打上時序標簽 ( Timestamp ) 后進行流式傳輸的過程。發送端源源不斷的采集音視頻數據,經過編碼、封包、推流,再經過中繼分發網絡進行擴散傳播,播放端再源源不斷地下載數據並按時序進行解碼播放。如此就實現了 “邊生產、邊傳輸、邊消費” 的直播過程。

 

理解以上兩個關於 視頻 和 直播 兩個基礎概念后,接下來我們就可以一窺直播的業務邏輯了。

一個完整的直播過程,包括但不限於以下環節:采集、處理、編碼、封包、推流、傳輸、轉碼、分發、拉流、解碼、播放。從推流到播放,再經過中間轉發環節,延遲越低,則用戶體驗越好。

 

第二個直播性能指標卡頓,是指視頻播放過程中出現畫面滯幀,讓人們明顯感覺到“卡”。單位時間內的播放卡頓次數統計稱之為卡頓率

 

造成卡頓的因素有可能是推流端發送數據中斷,也有可能是公網傳輸擁塞或網絡抖動異常,也有可能是終端設備的解碼性能太差。卡頓頻次越少或沒有,則說明用戶體驗越好。

 

第三個直播性能指標首屏耗時,指第一次點擊播放后,肉眼看到畫面所等待的時間。技術上指播放器解碼第一幀渲染顯示畫面所花的耗時。通常說的 “秒開”,指點擊播放后,一秒內即可看到播放畫面。首屏打開越快,說明用戶體驗越好。

 

如上三個直播性能指標,分別對應一個低延遲、高清流暢、極速秒開 的用戶體驗訴求。了解這三個性能指標,對優化移動直播 APP 的用戶體驗至關重要。

 

那么移動直播場景下具體而言有哪些常見的坑呢?

 

根據實踐總結下來的經驗,移動平台上視頻直播的坑主要可以總結為兩方面:設備差異,以及網絡環境這些場景下帶來的技術考驗。

移動網絡下,通常容易遇到網絡不穩定,連接被重置,斷線重連,一方面頻繁重連,建立連接需要開銷。另一方面尤其是發生 GPRS / 2G / 3G / 4G 切換時,帶寬可能出現瓶頸。當帶寬不夠,幀率較高/碼率較高的內容較難發送出去,這個時候就需要可變碼率支持。

 

即在推流端,可檢測網絡狀態和簡單測速,動態來切換碼率,以保障網絡切換時的推流流暢。

 

其次編碼、封包、推流 這一部分的邏輯也可以做微調,可以嘗試選擇性丟幀,比如優先丟視頻參考幀(不丟 I 幀和音頻幀 ),這樣也可以減少要傳輸的數據內容,但同時又達到了不影響畫質和版視聽流暢的目的。

移動直播場景其他優化措施

 

一、怎么優化打開速度,達到傳說中的 “秒開”?

 

大家可能會看到,市面上某些手機直播 APP 的打開速度非常快,一點就開。而某些手機直播 APP,點擊播放后要等好幾秒以后才能播放。是什么原因導致如此的天壤之別呢?

 

大部分播放器都是拿到一個完成的 GOP 后才能解碼播放,基於 FFmpeg 移植的播放器甚至需要等待音畫時間戳同步后才能播放(如果一個直播里邊沒有音頻只有視頻相當於要等待音頻超時后才能播放畫面)。

 

“秒開”可以從以下幾個方面考慮:

 

1. 改寫播放器邏輯讓播放器拿到第一個關鍵幀后就給予顯示。

 

GOP 的第一幀通常都是關鍵幀,由於加載的數據較少,可以達到 “首幀秒開”。

 

如果直播服務器支持 GOP 緩存,意味着播放器在和服務器建立連接后可立即拿到數據,從而省卻跨地域和跨運營商的回源傳輸時間。

 

GOP 體現了關鍵幀的周期,也就是兩個關鍵幀之間的距離,即一個幀組的最大幀數。假設一個視頻的恆定幀率是 24fps(即1秒24幀圖像),關鍵幀周期為 2s,那么一個 GOP 就是 48 張圖像。一般而言,每一秒視頻至少需要使用一個關鍵幀。

 

增加關鍵幀個數可改善畫質(GOP 通常為 FPS 的倍數),但是同時增加了帶寬和網絡負載。這意味着,客戶端播放器下載一個 GOP,畢竟該 GOP 存在一定的數據體積,如果播放端網絡不佳,有可能不是能夠快速在秒級以內下載完該 GOP,進而影響觀感體驗。

 

如果不能更改播放器行為邏輯為首幀秒開,直播服務器也可以做一些取巧處理,比如從緩存 GOP 改成緩存雙關鍵幀(減少圖像數量),這樣可以極大程度地減少播放器加載 GOP 要傳輸的內容體積。

 

2. 在 APP 業務邏輯層面方面優化。

 

比如提前做好 DNS 解析(省卻幾十毫秒),和提前做好測速選線(擇取最優線路)。經過這樣的預處理后,在點擊播放按鈕時,將極大提高下載性能。

 

一方面,可以圍繞傳輸層面做性能優化;另一方面,可以圍繞客戶播放行為做業務邏輯優化。兩者可以有效的互為補充,作為秒開的優化空間。

 

二、美顏等濾鏡如何處理?

 

在手機直播場景下,這就是一個剛需。沒有美顏功能的手機直播 APP,主播基本不愛用。可以在采集畫面后,將數據送給編碼器之前,將數據源回調給濾鏡處理程序,原始數據經過濾鏡處理完后,再送回給編碼器進行編碼即可。

 

除了移動端可以做體驗優化之外,直播流媒體服務端架構也可以降低延遲。例如收流服務器主動推送 GOP 至邊緣節點,邊緣節點緩存 GOP,播放端則可以快速加載,減少回源延遲。

三、如何保障直播持續播放流暢不卡頓?

 

“秒開”解決的是直播首次加載的播放體驗,如何保障直播持續播放過程中的畫面和聲音視聽流暢呢?因為,一個直播畢竟不是一個 HTTP 一樣的一次性請求,而是一個 Socket 層面的長連接維持,直到直到主播主動終止推流。

 

上述我們講過卡頓的定義:即播放時畫面滯幀,觸發了人們的視覺感受。在不考慮終端設備性能差異的情況下,針對網絡傳輸層面的原因,我們看看如何保障一個持續的直播不卡頓。

 

這其實是一個直播過程中傳輸網絡不可靠時的容錯問題。例如,播放端臨時斷網了,但又快速恢復了,針對這種場景,播放端如果不做容錯處理,很難不出現黑屏或是重新加載播放的現象。

 

為了容忍這種網絡錯誤,並達到讓終端用戶無感知,客戶端播放器可以考慮構建一個FIFO(先進先出)的緩沖隊列,解碼器從播放緩存隊列讀取數據,緩存隊列從直播服務器源源不斷的下載數據。通常,緩存隊列的容量是以時間為單位(比如3s),在播放端網絡不可靠時,客戶端緩存區可以起到“斷網無感”的過渡作用。

 

顯然,這只是一個“緩兵之計”,如果直播服務器邊緣節點出現故障,而此時客戶端播放器又是長連接,在無法收到對端的連接斷開信號,客戶端的緩沖區容量再大也不管用了,這個時候就需要結合客戶端業務邏輯來做調度。

 

重要的是客戶端結合服務端,可以做精准調度。在初始化直播推流之前,例如基於 IP 地理位置和運營商的精確調度,分配線路質量最優的邊緣接入節點。在直播推流的過程中,可以實時監測幀率反饋等質量數據,基於直播流的質量動態調整線路。

 

Q & A

 

1. 關鍵幀設置頻率一般是多少?有沒有根據接入動態設置?過長首屏秒會很難做到。

徐立:關鍵幀間隔越長,也就是 GOP 越長,理論上畫面越高清。但是生成 HLS 直播時,最小切割粒度也是一個 GOP,所以針對交互直播,通常不建議 GOP 設置太長。直播一般 2 個關鍵幀間隔即可。比如幀率是 24fps, 那么 2 個關鍵幀的間隔就是 48fps ,這個 GOP 就是2s。

 

2. 七牛這個直播是用的網宿加速?有遇到什么坑沒?

徐立:七牛在直播方面主要是自建節點,也支持融合眾多第三方 CDN 服務商,多樣化的線路組合為客戶提供更優質的服務。在和第三方 CDN 合作的過程中遇到的問題等有機會再做更細粒度的交流和分享。

 

3. RTMP 直播流除了優化線路外,還有什么加速手段嗎?

徐立:物理上優化線路,邏輯上優化策略,比如選擇性丟幀,不影響編碼畫質的前提下減輕傳輸體積。

 

4. OBS 推流,播放端 HLS 出現視/音頻不同步是哪個環節的問題?怎么優化?

徐立:有可能是采集端的問題,如果是采集端編碼環節就出現音畫不同步,可以在收流服務器上做音畫時間戳同步,這樣是全局的校對。如果是播放端解碼性能問題,那么需要調節播放邏輯,比如保證音畫時間戳強一致性的前提下,選擇性丟一部幀。

 

5. PPT 前幾頁中一個概念好像錯了,I 幀不是關鍵幀,IDR 幀才是。IDR 幀是 I 幀,但是 I 幀不一定是 IDR 幀。只有 IDR 幀才是可重入的。

徐立:中文都把 I 幀翻譯成關鍵幀了,不過既然提到了 IDR 幀,可以展開說明一下。所有的 IDR 幀都是 I 幀,但是並不是所有 I 幀都是 IDR 幀,IDR 幀是 I 幀的子集。I 幀嚴格定義是幀內編碼幀,由於是一個全幀壓縮編碼幀,通常用 I 幀表示 “關鍵幀”。IDR 是基於 I 幀的一個 “擴展”,帶了控制邏輯,IDR 圖像都是 I 幀圖像,當解碼器解碼到 IDR 圖像時,會立即將參考幀隊列清空,將已解碼的數據全部輸出或拋棄。重新查找參數集,開始一個新的序列。這樣如果前一個序列出現重大錯誤,在這里可以獲得重新同步的機會。IDR 圖像之后的圖像永遠不會使用 IDR 之前的圖像的數據來解碼。

 

6. 有沒有調研過 nginx rtmp module,為什么沒有用,對它有什么評價?

徐立:有調研過,nginx_rtmp_module 是單進程多線程,非 go 這種輕量級線程/協程用並發自然語義的方式編寫流業務。nginx 原本的代碼量較大(約 16 萬行,但和直播業務相關的功能並不是很多)。且主要靠寫 nginx.conf 做配置租戶,通常單租戶可以,但業務可擴展性方面不是很靈活,可滿足基本需求,不滿足高級功能。

 

7. 用到了那些開源軟件?編碼用的是 x264 嗎?直播服務器你們自己開發還是開源的?

徐立:直播服務器用 go 開發的,移動端編碼優先硬編,軟編用 x264

 

8. 請教一下用 OBS 推流到 nginx_rtmp_module 的時候是已經做了視頻壓縮了還是需要基於 OBS 再開發?

徐立:OBS 把編碼壓縮都做了,不需要再開發。

 

9. 視頻直播想在 HLS 流中無縫插入一段廣告的 ts 文件,有問題想請教一下:1、這段 ts 的分辨率是否一定要和之前的視頻流一致?2、pts 時間戳是否要和上一個 ts 遞增?

徐立:1、可以不一致。這種情況兩段視頻完全是獨立狀態,可以沒有任何關系,只需要插入 discontinue 標記,播放器在識別到這個標記之后重置解碼器參數就可以無縫播放,畫面會很平滑的切換。2、不需要遞增。舉個例子,視頻 A 正在直播,播放到 pts 在 5s 的時候,插入一個視頻 B,需要先插入一個 discontinue,再插入 B,等 B 播放完之后,再插入一個 discontinue,再插入 A,這個時候 A 的 pts 可以和之前遞增,也可以按照中間插入的 B 的時長做偏移,一般做點播和時移的時候 pts 會連續遞增,直播的話會算上 B 的時長。

 

PPT 下載地址

 

 

由於移動直播在實踐上還有非常多細節,本文未能全部覆蓋,感興趣的朋友歡迎在文章最后留言討論。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM