淺談網絡-直播都使用什麼流媒體協議?

說起直播這個詞現在好像並不陌生,在我認識的人中,這兩個月跳槽到有直播業務的公司的就三個人。有的問我做過直播嗎?哈哈,我只能明白的告訴他們我沒做過了,不過雖然沒具體做過這個業務,理論知識還是知道些的,下面就大體談下這種直播的過程大概是個什麼樣的邏輯吧。

視頻

要說直播的話,肯定首要了解的是視頻的相關知識。大家都知道視頻的很多後綴,例如AVI、MPEG、RMVB、MP4、MOV、FLV、WebM、H.261等等的吧,其實簡單的介紹視頻的話,就是一組連續播放的圖片,想象下幻燈片自動播放速度如果快的話是不是就像一個視頻了。其中快速播放的每一張圖片,我們稱之爲,每秒圖片播放速度,我們稱之爲幀率(FPS),播放速度快些的話,我們就不會感覺它是一張張圖片了。

但是這會引出一個問題,那就是如果那是一張張圖片的集合的話,那這種高清的視頻會多大,咱們一張按照700K來計算的話,每秒30幀,那一個小時的視頻將會達到1200多G,這就很恐怖來,尤其是在網絡上想要看一個高清視頻的話,簡直是絕望。那麼改如何解決呢?那就是編碼

之所以能夠通過編碼進行視頻壓縮,是因爲視頻和圖片有以下幾個特點。
1.空間冗餘:圖像的相鄰像素之間有較強的相關性,一張圖片相鄰像素往往是漸變的,不是突變的,沒必要每個像素都完整地保存,可以隔幾個保存一個,中間的用算法計算出來。
2.時間冗餘:視頻序列的相鄰圖像之間內容相似。一個視頻中連續出現的圖片也不是突變的,可以根據已有的圖片進行預測和推斷。
3.視覺冗餘::人的視覺系統對某些細節不敏感,因此不會每一個細節都注意到,可以允許丟失一些數據。
4.編碼冗餘::不同像素值出現的概率不同,概率高的用的字節少,概率低的用的字節多,類似霍夫曼編碼的思路。

當前主流的編碼套路:
套路一:ITU(International Telecommunications Union)的 VCEG(Video Coding Experts Group),這個稱爲國際電聯下的 VCEG。他們最初做視頻編碼,主要側重傳輸。
套路二:ISO(International Standards Organization)的 MPEG(Moving Picture Experts Group),這個是ISO 旗下的 MPEG,本來是做視頻存儲的。例如,編碼後保存在 VCD 和 DVD 中。當然後來也慢慢側重視頻傳輸了。

後來,ITU-T(國際電信聯盟電信標準化部門,ITU Telecommunication Standardization Sector)與 MPEG 聯合制定了 H.264/MPEG-4 AVC。經過編碼後的視頻就比之前體積小了很多,編碼後的二進制文件也就以我們最開始說的那幾種格式分別存儲。這些二進制通過某些協議的封裝就可以在網絡中傳播了。

具體視頻是怎麼進行編碼的,我就不做說明了,因爲我也不太清楚。

直播

對於視頻的基本有了些認識了以後,咱們開始今天的正題,直播都經歷了什麼過程?簡單的說,其實這個直播可以被分成以下幾個部分:
主 播 :錄製 -> 轉碼 -> 推流
服務端: 接流 -> 流處理 -> 分發
用 戶 :拉流 -> 解碼 -> 播放

主播對自己進行實時錄像,通過設備將實時視頻轉化爲二進制流,網絡協議將這編碼好的二進制視頻流推送到服務器。服務器接收到二進制流後,可以對視頻流進行一定的處理,例如解碼處理等,也即從一個編碼格式,轉成另一種格式。因爲觀衆使用的客戶端千差萬別,要保證他們都能看到直播,由於考慮到併發等系列的問題,可能會將流分發到不同的服務器上。用戶登陸進直播間後,就開始拉流到客戶端本地,並將二進制流進行解碼轉化,就可以播放了。

這個過程是不是看起來很簡單?那麼我們又是通過什麼,將流打包,發送到服務端的呢?直接推送二進制文件內容?當然不是。在這裏我們使用RTMP協議進行說明,當然由於RTMP是建立在TCP基礎上的,可能效率不是那麼讓人滿意,初次之外咱們還可以使用建立在UDP上的流媒體協議RTCP等。(當然這系列的協議挺多,並且各有所長,有需要的可以進行深入瞭解。)

RTMP 是基於 TCP 的,因而肯定需要雙方建立一個 TCP 的連接。在有 TCP 的連接的基礎上,還需要建立一個 RTMP 的連接,也即在程序裏面,你需要調用 RTMP 類庫的 Connect 函數,顯示創建一個連接。RTMP 爲什麼需要建立一個單獨的連接呢?

因爲它們需要商量一些事情,保證以後的傳輸能正常進行。主要就是兩個事情,一個是版本號,如果客戶端、服務器的版本號不一致,則不能工作。另一個就是時間戳,視頻播放中,時間是很重要的,後面的數據流互通的時候,經常要帶上時間戳的差值,因而一開始雙方就要知道對方的時間戳。

具體的交互流程如圖示所示,首先,客戶端發送 C0 表示自己的版本號,不必等對方的回覆,然後發送 C1 表示自己的時間戳。服務器只有在收到 C0 的時候,才能返回 S0,表明自己的版本號,如果版本不匹配,可以斷開連接。服務器發送完 S0 後,也不用等什麼,就直接發送自己的時間戳 S1。客戶端收到 S1 的時候,發一個知道了對方時間戳的 ACK C2。同理服務器收到 C1 的時候,發一個知道了對方時間戳的 ACK S2。則建立起了連接。之後,雙方需要互相傳遞一些控制信息,例如 Chunk 塊的大小、窗口大小等。


實際上,真正傳輸的時候,還需要建立一個流Stream,放在一個Message中(也就是一個RTMP Packet 包中)。格式如下圖所示


需要注意的是RTMP 在收發數據的時候並不是以 Message 爲單位的,而是把 Message 拆分成 Chunk 發送,而且必須在一個 Chunk 發送完成之後,才能開始發送下一個 Chunk。每個 Chunk 中都帶有 Message ID,表示屬於哪個 Message,接收端也會按照這個 ID 將 Chunk 組裝成 Message。

拆分示例如下圖所示:


前面連接的時候,設置的 Chunk 塊大小就是指這個 Chunk。將大的消息變爲小的塊再發送,可以在低帶寬的情況下,減少網絡擁塞。Chunk 的 Type=0,表示 Chunk 頭是完整的;Chunk Type=3,表示頭一樣就不再發送了;頭裏面 Timestamp 爲 1000,總長度 Length 爲 307,類型爲 9,是個視頻,Stream ID 爲 12346,正文部分承擔 128 個字節的 Data。

一個視頻直播裏面就那麼多門道,看樣子看直播這種事情是多麼的難得。且看且珍惜吧?順便問下大家都喜歡看直播嗎?喜歡的話一般在哪個平臺上看直播?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章