概述
所謂流媒體按照字面意思理解就是像流一樣的媒體,看起來像是廢話。流媒體現在司空見慣,所以一般人大概不會有疑問。事實上在流媒體還沒有出現的時候,基本上通過網絡播放電影就不太現實。通過網絡播放電影的時候必須先將整個文件下載到電腦上然后才能播放,所以一般都要緩沖很久,這也是為什么最開始迅雷等下載工具流行的原因,其實大多數都是用來下電影了。
流媒體最大的特點即是能夠做到邊下載邊播放,而不需要預先將整個文件全部下載完成之后才能播放,這樣極大的改善了用戶體驗,也提高了實時性,使得網絡直播成為可能。
那么流媒體是如何做到邊下載邊播放的呢,我們要了解流媒體系統的組成。
流媒體系統的組成
一個完整的流媒體系統由這些部分組成,信號采集,編碼,傳輸,解碼,輸出。
信號采集:我們所說的流媒體系統都是要在計算機系統上面進行處理的,而系統中最主要的元素是音頻和視頻,從物理上面來說音頻實際上是一種通過物理震動形成的機械波,音頻采集即是將這種物理波轉換為電信號進而轉換成二進制的音頻數據,一般采集得到的原始音頻數據是PCM數據。視頻是什么,視頻實際上是順序呈現出來的一幅幅連續的靜止圖像,所以視頻實際上是由一幅幅靜止的圖像組成,視頻的采集就是連續不斷的采集這些靜止的圖像的過程,這些一幅幅的圖像一般被稱為幀。那么這些被稱為幀的靜止圖像又是怎么被采集的呢,實際上圖像的表現形式並不是像聲音一樣的波,初中的物理我們就學過成像,我們之所以能夠看到圖像,是因為照射在物體上的光反射到我們的眼睛進入視網膜,傳導到視神經最后被我們大腦感知。所以圖像的采集是對光信號的采集與轉換,將光信號轉換為二進制的圖像幀的過程,一般我們得到的原始圖像數據格式是YUV格式。
編碼:什么是編碼,為什么要編碼。假設我們的網絡容量是無限的,傳輸速度也是無限大的,這當然是不需要編碼的。而實際上並不是,我們采集到的原始音視頻數據量是很大的,所以我們需要想辦法,將采集到的原始的音視頻二進制數據量盡量變小,方便在網絡上進行傳輸,同時又需要在還原(解碼)的時候盡量接近原始音視頻(損失,編碼也有分為有損和無損)。我們有時候稱編碼也叫壓縮編碼,其實壓縮這個概念類似我們平時的壓縮文件的原理一樣,舉個簡單的例子,例如有一個文本文件其內容是00000000000000000000000000000000000000000000000000 這么一串字符串,實際就是50個0字符,我們完全可以用最簡單的描述來壓縮,例如我們壓縮之后文件內容變成50’0’表示這里有50個0字符。在還原的時候這里直接用50個0字符填充即可,這樣是不是會節約大量的空間呢,如果不是50個0而是一萬個0字符呢,這樣經過壓縮之后的壓縮比會更大,也就是說重復的冗余數據越多,壓縮效率越高。當然實際的壓縮算法肯定沒這么簡單,說這么個簡單的例子只是為了說明原理而已。視頻的編碼算法有很多種,而且要復雜很多,每一種算法的運行效率,壓縮比,損失率都不一樣。而原理都是一樣的,在最常見的概念中,有幀內壓縮和幀間壓縮。
什么是幀內壓縮呢,假設一副圖像的背景是純紅色,前面站個人(拍證件照的場景)。在編碼的時候一副圖像被分成很多小塊(宏塊),這樣由於背景中會有很多相鄰的小塊都是純紅色,很多純紅色的小塊都可以根據其周圍的小塊推斷出來,而不需要單獨編碼,這就是幀內壓縮,這種壓縮是在一個幀內部進行的,跟其前后的圖像沒有關系。
那么幀間壓縮又是什么,如果一個視頻中相鄰的2副圖像,背景都是純紅色,背景中有一個球在圖像1中的位置是A點。在圖像2中的位置是B點。實際上如果把圖像1和圖像2疊在一起會發現他們除了球的位置不一樣之外,其他的部分是一樣的,也就是說這兩幅相鄰的圖像有很大一部分是相同的。在編碼第2副圖像的時候完全可以只編碼其與上一副圖像的不同部分。如果圖像1我們需要完全編碼,圖像1被稱為關鍵幀(一般稱為I幀),而圖像2在還原的時候需要參考圖像1,所以稱為參考幀(一般稱為P幀)。如果沒有關鍵幀,那么參考幀是無法還原的。當然在編碼的時候,一幀不僅可以參考其上一幀,還可以參考其下一幀(雙向預測的幀間壓縮),例如一個球從左滾到右,這種運動是可以做預測的。這種當前幀的編碼參考其相鄰圖像的算法就是幀間壓縮算法。
傳輸:經過采集,編碼我們現在已經獲得了音視頻數據幀,但是一般觀看視頻的一定不是在采集編碼的現場,否則就不需要傳輸了,傳輸的過程就是將編碼后的音視頻數據通過網絡(互聯網,或者有線電視網等,我們只討論互聯網)傳輸到希望觀看的觀眾那里。數據從一個地方傳遞到另一個地方這個過程就是傳輸。傳輸過程中最重要的當然是流媒體協議了,為什么還需要流媒體協議?在流媒體播放的時候會有一些播放邏輯,例如,播放,暫停,跳轉,停止,快進,快退。另外在編碼之后的數據從一端傳遞到另一端,另一端需要將編碼之后的數據還原成編碼之前的原始數據才能播放。如何還原?必須得知道之前編碼是使用什么算法編碼的,在還原的時候才能采用相應的解碼算法進行還原。那么編碼的時候使用的是什么算法,這個也需要從一端通知到另一端,這個信息也是在流媒體傳輸協議中會有的。除此之外還會有其他的一些邏輯信息,例如視頻的幀率,關鍵幀的間隔(GOP Size)等。總結為一句話,編碼過后的音視頻數據通過網絡從一端傳遞到另一端,在另一端對數據還原的時候需要一些信息,並且需要支持一些播放場景的邏輯,這些都需要在流媒體協議中進行描述。目前最流行的流媒體協議,Adobe公司的RTMP,RTSP,微軟的MMS等。
解碼:經過編碼壓縮的數據必須還原成編碼之前的原始數據才能播放顯示,這個還原過程就是解碼的過程。
輸出:輸出的過程就是播放出來的過程,與采集的時候一樣,實際上這是將采集的原始音視頻數據經過模數轉換轉換成物理信號,視頻信號通過顯示器顯示出來,音頻信號通過音箱放出來。
媒體文件封裝
我們之前討論的是媒體的流式播放,其實這個流式主要是指傳輸是流動的,而且視頻幀可以邊傳輸,邊解碼播放。如果我們希望將播放的內容保存到磁盤上,就必須要有一種文件格式來組織這些數據,以一定的結構來保存這些音視頻數據。為什么不直接將網絡傳輸過來的內容直接寫到一個文件中保存呢,如果直接將所有傳輸過來的數據不加任何結構組織直接保存的話,那么在播放的時候如何播放?如何知道這些二進制數據哪些是音頻哪些是視頻,如何知道每一幀音視頻數據在文件中的邊界,如何知道該音視頻的內容是通過什么編碼算法編碼的,如何知道播放一幀數據之后再隔多長時間播放下一幀數據,如果像有的電影文件需要多種字幕又如何組織。所以這就必須要有一種文件格式能夠組織這些音視頻數據並且附加這些播放必須的信息在文件中。這就是媒體文件的封裝。現存有很多種媒體文件,有的是某個公司的專利,有的是國際標准,例如MP4,MP3,AVI,RMVB等等等等。所以如果要保存這些流媒體數據到文件中,則必須通過一定的文件封裝格式將這些音視頻數據保存在具有一定格式的媒體文件中。
傳輸協議
目前使用的最多的流媒體傳輸協議當然是RTMP和RTSP了。微軟的MMS基本在工作中接觸的不多,特別是當前比較火爆的互聯網直播。還有一個需要特別提到的HTML5出來之后,很多以前通過flash客戶端承載RTMP協議的播放方式被以HLS替換了。但是實時性要求比較高的直播還是需要通過RTMP或者RTSP協議。HLS嚴格來說,其實我感覺都不能叫流媒體協議,HLS實際上基本可以認為是一個TS文件的播放列表,沒有流媒體協議中的那些邏輯功能,播放,暫停,停止。應該說HLS僅僅是特定情況下出來的,主要是針對跨平台的瀏覽器進行直播。我們所看到的HLS大部分都是通過移動設備,PC機器上的瀏覽器來播放的。
需要指出的是,在與蘋果的HLS爭奪市場的過程中,同時出現了多種類似的技術,都是用的HTTP協議,一般我們稱為HTTP漸進式下載。例如微軟的Live Smooth Streaming 中文名稱為直播平滑流,這種技術需要微軟IIS7及以上版本的web服務器和Silverlight客戶端支持。另外一種是開源的技術好像並不是某個公司出品,叫Http Pseudo-Streaming 中文名是偽流。目前只看到一個基於Apache服務器的插件H264 Streaming Module for Apache,客戶端貌似也是使用Flash Player。還有一種叫HTTP Dynamic Streaming 中文稱做HTTP動態流,是Adobe公司的技術方案,其服務端需要Flash Media Server支持,客戶端則是Flash Player。其實現在的Flash Media Server 也已經支持HLS了。蘋果的HLS就不說了現在很多服務器以及開源代碼都支持HLS,客戶端呢只要支持HTML5的瀏覽器基本也都支持HLS,現在的HLS已經是主流。最后要說的是新出現的一種技術標准,MPEG-DASH目的為了統一這些技術方案,還在標准化中,如果真的標准化,也有可能取代HLS,畢竟HLS還沒有稱為正式標准,只是蘋果公司提交了個草案。
RTMP協議的發展得益於flash播放器的廣泛傳播,而RTSP協議則得益於其協議的開源。本系列要講解的crtmpserver就是基於RTMP協議的開源流媒體服務器,開發語言為C++。等同的產品還有Red5 語言為Java也是開源。另外一個比較有影響力是wowza屬於閉源產品。此外RTMPDump項目是用的比較多的RTMP客戶端開源項目,其中的librtmp庫使用的很廣泛,C語言編寫。另外OpenRTMFP是基於p2p技術的RTMP。