RTMP延遲優化之路

最近在作RTMP直播,相關內容能夠查看往期的文章。那麼功能完成好了以後,才發現最難的一個問題還在後面,那就是RTMP的延遲如何下降?緩存


在具體分析前,首先咱們先要理清思路,若是是一個RTMP推拉流的過程:微信


那麼針對這個流程,咱們能夠看出主要的延遲只會在這三個地方發生,那麼咱們來分析哪些地方可能形成延遲變大。網絡


推流端併發


對於一個推流端,首先涉及到的就是編碼,也就是對視頻流進行封裝。這裏涉及到一個重要的概念GOP,指的是視頻中兩個I幀的間隔。那麼咱們先了解一下視頻編碼中的I幀、B幀和P幀。
性能


I幀、B幀、P幀動畫


咱們知道視頻或者說是動畫利用的是人眼的視覺殘留的原理,經過一系列的圖片,達成動畫的效果。因此視頻傳輸本質上也是傳輸了一幀幀的畫面數據。ui


那麼若是咱們每一幀的畫面都是完整的畫面,大概須要多少數據呢?咱們假設咱們呢傳輸的是1080P的8bit圖組成的視頻,那麼每一幀就是1920x1080x8x3=49766400‬bit,也就是47.46MB,那麼若是視頻幀率是30Hz,那麼每秒也就是1423.82MB。也就是在這種狀況下,咱們每秒傳輸的數據就是1.39MB。這個數據量其實在不少狀況下是比較大的,試想若是觀看這樣的視頻10分鐘,那麼流量就是834MB。
編碼


爲了解決這個問題,目前視頻傳輸和保存都採用了視頻壓縮技術,好比H.264。在這種技術下,編碼器將圖片分紅三種,也就是I幀、B幀和P幀:spa

  • I幀:也就是關鍵幀(Intra-coded picture 內部編碼幀),指的是完整的畫面,在這個幀中,有着完整的畫面信息。.net

  • B幀:雙向內插幀(Bidirectional predicted picture 雙向參考幀),這個畫面是不完整的,若是想要依靠這個畫面獲得完整的畫面信息,那麼就須要參考前一幀和後一幀。這個是包含畫面信息最少的幀。

  • P幀:前向預測幀(Predicted picture 預測幀),這個畫面也是不完整的,若是想要依靠這個畫面獲得完整的畫面信息,須要參考前一幀。




而視頻編碼就是生產一個個GOP(Group of Picture),也就是包含一個關鍵幀I幀的一組圖片。而GOP長度就是兩個I幀的距離。那麼GOP對延遲有什麼影響呢?由於GOP的存在,致使播放端的視頻解碼器須要拿到關鍵幀才能解碼,若是一開始拿不到關鍵幀,那麼解碼器只能等待,這時就會出現黑屏,一直等到關鍵幀的到來。而這個最長時間是多少呢?就是一個GOP的長度。


因此爲了防止黑屏的出現,不少時候服務端都會緩存前一個GOP,這就致使客戶端始終從前一個I幀播放,那麼延遲至少是一個GOP的長度。這時不少朋友確定會想那麼咱們就減小GOP的長度不就能夠了麼?這個想法的確是對的,不少實時性要求很高的地方就是這麼作的,之因此不是全部場景都這麼作,是由於GOP過低會致使編碼率壓縮率變低,圖像質量也沒有那麼好。


緩存


由於RTMP是基於TCP的,因此存在累積延遲的問題,也就是在網絡條件很差的時候 ,爲了保證傳輸的可靠性,會將失敗的包保存起來,等待網絡條件好的時候一併發出。可是對於直播來講,這樣無疑增長了延遲,若是網絡波動較大,那麼緩存反而是有害的,因此通常來講都會將推流端的緩存設置到儘量的小。


RTMP服務端


對於服務端來講,須要考慮的首先和上面同樣,也就是緩存,若是是低延時要求,那麼首先服務端的緩存也不能設計過大。那麼除了緩存服務端還須要考慮上面呢?


Merged-Read


RTMP的讀效率很是低,首先要先讀一個字節,判斷是哪一個chunk,而後讀取header,再讀取payload。因此通常爲了提升性能,服務端會採用merged-read,也就是一次讀取幾毫秒的數據,進行一次讀取。這樣的壞處就是服務端至少要接受到這麼多數據才能進行讀取,而這個就是延遲的大小。因此若是是低延時的場景,那麼就須要關閉這個功能,讓服務端每次收到一個包就解析。


Merged-Write


一樣,服務端爲了提供效率,也會進行merged-write,也就是一次發送幾毫秒的數據到客戶端,這個一樣也會致使延遲。好處是能夠支持的客戶端會變多。因此在低延遲的場景中咱們須要根據要求進行權衡,將這個設置到較小的值。


GOP


結果推流端的內容,服務端應當關閉GOP緩存,不緩存前一個GOP。


累積延遲


一樣,由於拉流端可能採用RTMP或者HTTP-FLV,也都是基於TCP的,因此會存在累積延遲,處理這個問題的解決方法就是減小緩存區的大小,若是發現太多的緩存就丟棄。


拉流端


拉流端要考慮的其實就是一個,那就是緩存的設置以及緩存的策略。這裏由於不是專業的,只能說一下思路,就是獲取緩存的長度和當前播放的位置,而後二者的差就是具體的延遲。因此須要設置個閾值,當大於這個值時,就進行動態的快進。這樣就能夠達到無感知的延遲縮小。


總結


經過上面分析,咱們能夠看出,RTMP中的延遲是沒法避免的問題,咱們能作的就是儘可能根據需求來權衡延遲和性能。而這裏面最重要的就是緩存,緩存的好處就是穩定,可是它的壞處也很明顯,那就是帶來延遲的增長。



本文分享自微信公衆號 - 雨夜隨筆(yuye_suibi)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索