1. 程式人生 > >[原創]直播伺服器簡單實現 http_flv和hls 內網直播桌面

[原創]直播伺服器簡單實現 http_flv和hls 內網直播桌面

注意:不支援xp系統,啟動失敗請先安裝dx11。win10的視訊流可能會是黑屏,需要選擇low api。

直播都不陌生了,如今主流的協議分析的對比圖,個人見解。

協議

httpflv

rtmp

hls

dash

傳輸方式

http流

tcp流

http

http

視訊封裝格式

flv

flv tag

Ts檔案

Mp4 3gp webm 切片

延時

資料分段

連續流

連續流

切片檔案

切片檔案

Html5播放

可通過html5解封包播放(flv.js)

不支援

可通過c(hls.js)

 直接播放或者html5解封包播放

http_flv&rtmp

這兩個協議實際上傳輸資料是一樣的,資料都是flv檔案的tag。http_flv是一個無限大的http流的檔案,相比rtmp就只能直播,而rtmp還可以推流和更多的操作。但是http有個好處,就是是以80http通訊的,穿透性強,而且rtmp是非開放協議。

這兩個協議是如今直播平臺主選的直播方式,主要原因就是延時極低。

hls

hls是Apple推出的直播協議,是通過視訊流切片成檔案片段來直播的。客戶端首先會請求一個m3u8檔案,裡面會有不同位元速率的流,或者直接是ts檔案列表,通過給出的ts檔案地址去依次播放。在直播的時候,客戶端會不斷請求m3u8檔案,檢查ts列表是否有新的ts切片。

這種方式直播的主要弊端就是延遲過大,最小延時為ts單個檔案的時長。

dash

dash實際工作原理和hls一樣的,只不過不是mpegts檔案,dash可以支援多種切片檔案,比如mp4切片。當為mp4切片,客戶端直接可用js控制利用html5直接播放。同樣的,dash有延時。

http-flv到底是怎麼直播?

這裡我們主要研究httpflv和hls。看了主流幾個web直播平臺,發現幾乎都是以httpflv為主來直播的,那麼這麼火httpflv到底是怎麼達到直播的?http_flv其實就是一個無限長的http的flv檔案流,客戶端邊接受邊播放 。

首先我們都知道在媒體格式裡,幾乎都以h264視訊編碼。如今httpflv直播的flv資料也都是h264&aac為主的。flv封裝單元是以tag來表示的,一個tag可以是音訊tag或者視訊tag,或者指令碼tag及其其他型別。

值得注意的是flv裡面位元組序是網路位元組序,

flv的格式:

1flvheader+[指令碼tag(metadata)]+[第一個視訊tag(h264_spspps)]+[第一個音訊tag(aac_header)]+[第二個視訊tag(h264第一個關鍵幀)]+ 後面就是音訊和視訊tag互動存在

tag的格式:

1TYPE[1byte] + body size[3byte] + timestamp [4byte] +streamID [3byte] +[body data]+[previousTagSize 4byte]

這裡的timestamp是這樣存在的[ time tamp 3b,time tamp ex 1b]

h264視訊tagbody:

這裡儲存的h264是沒有nal分割符的,在t的body裡面是這樣儲存的,

1[isKeyFrame(1byte)]+0x01+[compositionTime 3byte]+[h264 size 4byte]

compositionTime是h264編碼結果dts和pts之間的偏移。

aac視訊tag的body:

10xaf+0x01+aac raw

以上就是flv格式的詳細說明,可以看出格式簡單,封裝的前後資料關聯很小,當我們得到音訊頭和視訊頭,就可以從後面任意的一個關鍵幀開始播放。

當然想要httpflv正常播放,不能缺少matedata,就是第一個指令碼tag裡面,這裡面指定了解析度,音視訊編碼格式等。

 httpflv直播實際上單純就是往客戶端傳送flvtag,當然是先發送flv前面那幾個關鍵的tag,然後第一幀是關鍵幀。

假如客戶端是obs推流軟體,以rtmp方式向伺服器推流,在開始握手及其建立stream完成以及傳送Metadata完成,及其一系列資料傳送完畢,伺服器就向obs傳送publish result指令,此後,obs就開始向伺服器推送flv tag資料,開始直播,而伺服器也得到了flv資料。

當某個客戶端想要來獲取直播資料,比如httpflv的方式來觀看直播,伺服器會怎麼做呢?

伺服器會先發送前面幾個flvtag,header+metadata+spspps+aacheader,當這幾個tag傳送完畢,伺服器會從直播流tag中,找到最新的視訊關鍵幀tag,從這個關鍵幀tag開發資料,為什麼呢?因為視訊流是IBP幀相互存在的,I是完整資料,BP解碼都需要I幀和前面的幀,所以,正常視訊資料,必須是從I幀開始傳送的。這裡就涉及到gop間距了,rtmp低延時秒開就是這個原理。當然傳送的時候,每個連線的tag開始時間戳戳要從0開始遞增的。

至此,httpflv客戶端就可以接受到flv流資料,解碼觀看直播了。

hls到底是怎麼直播?

hls就相對簡單粗暴了,伺服器將直播流資料的h264和aac,封裝切片成一個個的ts檔案。客戶端獲取直播的資料的時候,先請求m3u8檔案,下面就是一個m3u8的檔案,

#EXTM3U#EXT-X-VERSION:3#EXT-X-TARGETDURATION:5 ts最大時常5s#EXT-X-MEDIA-SEQUENCE:2 第一個ts檔案的標識#EXTINF:4.993,//第一個ts檔案,時長4.993,url地址/hls/2.ts/hls/2.ts#EXTINF:4.034,/hls/3.ts#EXTINF:4.980,/hls/4.ts

如果是直播,客戶端會不停的去請求這個m3u8檔案,當這個列表有新的ts檔案,客戶端會請求新的ts檔案追加到本地播放序列。

關於ts的封包,ts的封裝格式要比flv更復雜,主要的資料單元是ts包,每個包有pid,一個包固定大小普通沒有crc的為188,主要分為三類ts包,pat,pmt,pes,pat就是第一個包,當解析的時候會在ts包列表裡找pid為0x0的包,就是pat包,pat大概作用就是入口的意思,pat裡面有pmt包的pid,pmt裡面儲存的是流的包的pid,比如指定音訊包pid是0x102,視訊包pid是0x101,後面的0x102和0x101的包就是pes包了,將pes包解析併合並出原始流,就能解碼播放了。

 小程式

知道了如何玩直播,於是寫了一個小的程式,該程式會錄製本機桌面和輸出音訊以及麥克風,編碼為h264和aac,同時在本機利用windows IOCP(I/O Completion Port) 簡易的建立一個伺服器,提供web服務和直播服務,支援httpflv和hls直播。

以下是小程式的架構圖:

執行截圖:

啟動後可選擇,填寫埠號和位元速率,然後選擇直播方式,黑屏換low api。

程式使用的三個庫:

libx264 視訊編碼

libfaac 音訊編碼

swscale brga轉yuv420

 注意:不支援xp系統,啟動失敗請先安裝dx11。