說起直播這個詞現(xiàn)在好像并不陌生兔毒,在我認識的人中捣鲸,這兩個月跳槽到有直播業(yè)務的公司的就三個人瑟匆。有的問我做過直播嗎?哈哈栽惶,我只能明白的告訴他們我沒做過了愁溜,不過雖然沒具體做過這個業(yè)務,理論知識還是知道些的外厂,下面就大體談下這種直播的過程大概是個什么樣的邏輯吧冕象。
視頻
要說直播的話,肯定首要了解的是視頻的相關(guān)知識汁蝶。大家都知道視頻的很多后綴渐扮,例如AVI论悴、MPEG、RMVB墓律、MP4膀估、MOV、FLV耻讽、WebM察纯、H.261等等的吧,其實簡單的介紹視頻的話针肥,就是一組連續(xù)播放的圖片饼记,想象下幻燈片自動播放速度如果快的話是不是就像一個視頻了。其中快速播放的每一張圖片慰枕,我們稱之為幀具则,每秒圖片播放速度,我們稱之為幀率(FPS)捺僻,播放速度快些的話乡洼,我們就不會感覺它是一張張圖片了。
但是這會引出一個問題匕坯,那就是如果那是一張張圖片的集合的話束昵,那這種高清的視頻會多大,咱們一張按照700K來計算的話葛峻,每秒30幀锹雏,那一個小時的視頻將會達到1200多G,這就很恐怖來术奖,尤其是在網(wǎng)絡(luò)上想要看一個高清視頻的話礁遵,簡直是絕望。那么改如何解決呢采记?那就是編碼佣耐。
之所以能夠通過編碼進行視頻壓縮,是因為視頻和圖片有以下幾個特點唧龄。
1.空間冗余:圖像的相鄰像素之間有較強的相關(guān)性兼砖,一張圖片相鄰像素往往是漸變的,不是突變的既棺,沒必要每個像素都完整地保存讽挟,可以隔幾個保存一個,中間的用算法計算出來丸冕。
2.時間冗余:視頻序列的相鄰圖像之間內(nèi)容相似耽梅。一個視頻中連續(xù)出現(xiàn)的圖片也不是突變的,可以根據(jù)已有的圖片進行預測和推斷胖烛。
3.視覺冗余::人的視覺系統(tǒng)對某些細節(jié)不敏感眼姐,因此不會每一個細節(jié)都注意到诅迷,可以允許丟失一些數(shù)據(jù)。
4.編碼冗余::不同像素值出現(xiàn)的概率不同妥凳,概率高的用的字節(jié)少竟贯,概率低的用的字節(jié)多,類似霍夫曼編碼的思路逝钥。
當前主流的編碼套路:
套路一:ITU(International Telecommunications Union)的 VCEG(Video Coding Experts Group)屑那,這個稱為國際電聯(lián)下的 VCEG。他們最初做視頻編碼艘款,主要側(cè)重傳輸持际。
套路二:ISO(International Standards Organization)的 MPEG(Moving Picture Experts Group),這個是ISO 旗下的 MPEG哗咆,本來是做視頻存儲的蜘欲。例如,編碼后保存在 VCD 和 DVD 中晌柬。當然后來也慢慢側(cè)重視頻傳輸了姥份。
后來,ITU-T(國際電信聯(lián)盟電信標準化部門年碘,ITU Telecommunication Standardization Sector)與 MPEG 聯(lián)合制定了 H.264/MPEG-4 AVC澈歉。經(jīng)過編碼后的視頻就比之前體積小了很多,編碼后的二進制文件也就以我們最開始說的那幾種格式分別存儲屿衅。這些二進制通過某些協(xié)議的封裝就可以在網(wǎng)絡(luò)中傳播了埃难。
具體視頻是怎么進行編碼的,我就不做說明了涤久,因為我也不太清楚涡尘。
直播
對于視頻的基本有了些認識了以后,咱們開始今天的正題响迂,直播都經(jīng)歷了什么過程考抄?簡單的說,其實這個直播可以被分成以下幾個部分:
主 播 :錄制 -> 轉(zhuǎn)碼 -> 推流
服務端: 接流 -> 流處理 -> 分發(fā)
用 戶 :拉流 -> 解碼 -> 播放
主播對自己進行實時錄像蔗彤,通過設(shè)備將實時視頻轉(zhuǎn)化為二進制流川梅,網(wǎng)絡(luò)協(xié)議將這編碼好的二進制視頻流推送到服務器。服務器接收到二進制流后幕与,可以對視頻流進行一定的處理,例如解碼處理等镇防,也即從一個編碼格式啦鸣,轉(zhuǎn)成另一種格式。因為觀眾使用的客戶端千差萬別来氧,要保證他們都能看到直播诫给,由于考慮到并發(fā)等系列的問題香拉,可能會將流分發(fā)到不同的服務器上。用戶登陸進直播間后中狂,就開始拉流到客戶端本地凫碌,并將二進制流進行解碼轉(zhuǎn)化,就可以播放了胃榕。
這個過程是不是看起來很簡單盛险?那么我們又是通過什么,將流打包勋又,發(fā)送到服務端的呢苦掘?直接推送二進制文件內(nèi)容?當然不是楔壤。在這里我們使用RTMP協(xié)議進行說明鹤啡,當然由于RTMP是建立在TCP基礎(chǔ)上的,可能效率不是那么讓人滿意蹲嚣,初次之外咱們還可以使用建立在UDP上的流媒體協(xié)議RTCP等递瑰。(當然這系列的協(xié)議挺多,并且各有所長隙畜,有需要的可以進行深入了解抖部。)
RTMP 是基于 TCP 的,因而肯定需要雙方建立一個 TCP 的連接禾蚕。在有 TCP 的連接的基礎(chǔ)上您朽,還需要建立一個 RTMP 的連接,也即在程序里面换淆,你需要調(diào)用 RTMP 類庫的 Connect 函數(shù)哗总,顯示創(chuàng)建一個連接。RTMP 為什么需要建立一個單獨的連接呢倍试?
因為它們需要商量一些事情讯屈,保證以后的傳輸能正常進行。主要就是兩個事情县习,一個是版本號涮母,如果客戶端、服務器的版本號不一致躁愿,則不能工作叛本。另一個就是時間戳,視頻播放中彤钟,時間是很重要的来候,后面的數(shù)據(jù)流互通的時候,經(jīng)常要帶上時間戳的差值逸雹,因而一開始雙方就要知道對方的時間戳营搅。
具體的交互流程如圖示所示云挟,首先,客戶端發(fā)送 C0 表示自己的版本號转质,不必等對方的回復园欣,然后發(fā)送 C1 表示自己的時間戳。服務器只有在收到 C0 的時候休蟹,才能返回 S0沸枯,表明自己的版本號,如果版本不匹配鸡挠,可以斷開連接辉饱。服務器發(fā)送完 S0 后,也不用等什么拣展,就直接發(fā)送自己的時間戳 S1彭沼。客戶端收到 S1 的時候备埃,發(fā)一個知道了對方時間戳的 ACK C2姓惑。同理服務器收到 C1 的時候,發(fā)一個知道了對方時間戳的 ACK S2按脚。則建立起了連接于毙。之后,雙方需要互相傳遞一些控制信息辅搬,例如 Chunk 塊的大小唯沮、窗口大小等。
實際上堪遂,真正傳輸?shù)臅r候介蛉,還需要建立一個流Stream,放在一個Message中(也就是一個RTMP Packet 包中)溶褪。格式如下圖所示
需要注意的是RTMP 在收發(fā)數(shù)據(jù)的時候并不是以 Message 為單位的币旧,而是把 Message 拆分成 Chunk 發(fā)送,而且必須在一個 Chunk 發(fā)送完成之后猿妈,才能開始發(fā)送下一個 Chunk吹菱。每個 Chunk 中都帶有 Message ID,表示屬于哪個 Message彭则,接收端也會按照這個 ID 將 Chunk 組裝成 Message鳍刷。
拆分示例如下圖所示:
前面連接的時候,設(shè)置的 Chunk 塊大小就是指這個 Chunk俯抖。將大的消息變?yōu)樾〉膲K再發(fā)送输瓜,可以在低帶寬的情況下,減少網(wǎng)絡(luò)擁塞。Chunk 的 Type=0前痘,表示 Chunk 頭是完整的;Chunk Type=3担忧,表示頭一樣就不再發(fā)送了芹缔;頭里面 Timestamp 為 1000,總長度 Length 為 307瓶盛,類型為 9最欠,是個視頻,Stream ID 為 12346惩猫,正文部分承擔 128 個字節(jié)的 Data芝硬。
一個視頻直播里面就那么多門道,看樣子看直播這種事情是多么的難得轧房。且看且珍惜吧拌阴?順便問下大家都喜歡看直播嗎?喜歡的話一般在哪個平臺上看直播奶镶?