1. 程式人生 > >直播技術學習筆記(直播協議+流媒體伺服器+音視訊處理+FFmpeg)

直播技術學習筆記(直播協議+流媒體伺服器+音視訊處理+FFmpeg)

直播協議

RTMP(Real Time Messaging Protocol)

簡介

Time Messaging Protocol,實時訊息傳送協議

RTMP是Adobe公司為Flash播放器和伺服器之間音訊、視訊和資料傳輸開發的開放協議。

協議:長連線TCP

原理:每個時刻的資料,收到後立即轉發

延遲:1~3秒

優點

  • 實時性高:一般能做到3秒內。
  • 支援加密:rtmpe和rtmps為加密協議。
  • 穩定性高:在PC平臺上flash播放的最穩定方式是rtmp,如果做CDN或者大中型叢集分發,選擇穩定性高的協議一定是必要的。
  • 一般主流編碼器都支援該協議。

缺點

  • 協議複雜:開發者寫起來累,效率也不行。
  • Cache麻煩:流協議做快取不方便。

RTSP(Real Time Streaming Protocol)

簡介

實時流協議(Real Time Streaming Protocol,RTSP)是一種網路應用協議,專為娛樂和通訊系統的使用,以控制流媒體 伺服器。該協議用於建立和控制終端之間的媒體會話。媒體伺服器的客戶端釋出VCR命令,例如播放,錄製和暫停,以便於實時控制從伺服器到客戶端(視訊點播)或從客戶端到伺服器(語音錄音)的媒體流。

Time Streaming Protocol,實時流傳輸協議)

優點

●  延遲低,一般都能夠做到500ms。

●  頻寬好,時效率高。

●  倍速播放,主要是回放的時候提供的功能。

●  控制精準,任意選擇播放點。

缺點

●  服務端實現複雜。

●  代理伺服器弱:數量少,優化少。

●  無路由器防火牆穿透

●  管流分離:需要1-3個通道。

HLS(HTTP Live Streaming)

簡介

HTTP Live Streaming(縮寫是HLS)是一個由蘋果公司提出的基於HTTP流媒體網路傳輸協議。是蘋果公司QuickTime X

iPhone軟體系統的一部分。它的工作原理是把整個流分成一個個小的基於HTTP的檔案來下載,每次只下載一些。當媒體流正在播放時,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應不同的資料速率。在開始一個流媒體會話時,客戶端會下載一個包含元資料的extended M3U (m3u8) playlist檔案,用於尋找可用的媒體流。

協議:短連結HTTP

原理:集合一段時間資料,生成ts切片檔案,更新m3u8

延遲:>10秒

優點

●  效能好:和http一樣。

●  穿牆:和http一樣。

●  原生支援很好:iOS上支援完美,Android上支援差些。PC/flash上現在也有各種as外掛支援HLS。

缺點

●  實時性差:與ts切片長度有關,大約3個切片長度時間的延遲,基本上HLS的延遲在10秒以上。

●  檔案碎片:若分發HLS,碼流低,切片較小時,會導致太多的檔案碎片

流媒體伺服器

主要介紹

  1. NGINX-rtmp
  2. Node-media-server
  3. livego
  4. SRS

NGINX-rtmp

簡介:基於NGINX的流媒體伺服器

支援協議:RTMP/HLS/MPEG-DASH

支援平臺:Linux/FreeBSD/MacOS/Windows

官網:https://github.com/arut/nginx-rtmp-module

如果是windows平臺,可直接下載編譯好的檔案

https://github.com/illuspas/nginx-rtmp-win32

Node-media-server

簡介:A Node.js implementation of RTMP/HTTP-FLV/WS-FLV/HLS/DASH/MP4 Media Server

支援協議:RTMP/HTTP-FLV/WS-FLV/HLS/DASH

支援平臺:Windows/Linux/Unix

官網:https://github.com/illuspas/Node-Media-Server/

一分鐘部署一個流媒體服務

https://github.com/illuspas/Node-Media-Server/wiki/%E4%B8%80%E5%88%86%E9%92%9F%E9%83%A8%E7%BD%B2%E4%B8%80%E4%B8%AA%E6%B5%81%E5%AA%92%E4%BD%93%E6%9C%8D%E5%8A%A1

livego

簡介:純 Go 寫的直播伺服器

支援協議:RTMP/AMF/HLS/HTTP-FLV

支援平臺:Windows/Linux/MacOS

官網:https://github.com/gwuhaolin/livego

SRS

簡介:SRS定位是運營級的網際網路直播伺服器叢集,追求更好的概念完整性和最簡單實現的程式碼。

支援協議:RTMP/RTSP/HSL/HTTP-FLV

支援平臺:Linux/MacOS

官網:https://github.com/ossrs/srs

這個功能比較強大,官網文件很詳細,具體去官網看吧

如果想在windows體驗,可下載網友修改的版本

https://github.com/illuspas/srs-win32

導致延遲因素

網路延時

網路延時這裡指的是從主播端採集,到觀眾端播放,之間的時間差。這裡不考慮主播段採集對視訊進行編碼的時間,以及觀眾端觀看對視訊進行解碼的時間,僅考慮網路傳輸中的延時。例如說下圖中的網路延時:

另外,資料傳輸過程中還涉及到邏輯上的互動,例如包的重傳以及確認,以及快取上的一些邏輯等,會在這個基礎上又增加很多。

那麼來簡單估算一下大概的網路延時。眾所周知,光在真空中的速度約為300,000km/s,而在其他介質中光速會大大降低,所以在普通光纖中,工程上一般認為傳輸速度是200,000km/s。從現實上來說,可以參考如下:

路線

距離(km)

往返時延(ms)

北京到上海

1,200

12

北京到紐約

11,000

110

赤道周長

40,000

400

所以說,在節點較少、網路情況較好的情況下,那麼網路延時對應也是最小,加上一定的快取,可以控制延時在1s~2s左右。但是節點多、網路差的情況下,網路延時會對應增大,經驗來說延時可以達到15s以上。

網路抖動

網路抖動,是指資料包的到達順序、間隔和發出時不一致。比如說,傳送100個數據包,每個包間隔1s發出。結果第27個包在傳輸過程中遇到網路擁塞,造成包27不是緊跟著26到達的,而是延遲到87後面才達。在直播中,這種抖動的效果實際上跟丟包是一樣的。因為你不能依照接收順序把內容播放出來,否則會造成失真。

網路抖動,會造成播放延時對應增大。如果網路中抖動較大,會造成播放卡頓等現象。

如上圖所示,主播端t3和t5發出的包,分別在t3'和t5'到達,但是中間延時增大,即發生了網路抖動。這樣造成觀眾端觀看視訊的延時會不斷增大。

網路丟包

CDN直播中用到的RTMP、HLS、HTTP FLV等協議都是在TCP的基礎之上。TCP一個很重要的特性是可靠性,即不會發生資料丟失的問題。為了保證可靠性,TCP在傳輸過程中有3次握手,見下圖。首先客戶端會向服務端傳送連線請求,服務端同意後,客戶端會確認這次連線。這就是3次握手。接著,客戶端就開始傳送資料,每次傳送一批資料,得到服務端的“收到”確認後,繼續傳送下一批。TCP為了保證傳到,會有自動重傳機制。如果傳輸中發生了丟包,沒有收到對端發出的“收到”訊號,那麼就會自動重傳丟失的包,一直到超時。

由於網際網路的網路狀況是變化的,以及主播端的網路狀況是無法控制的。所以當網路中丟包率開始升高時,重傳會導致延時會不斷增大,甚至導致不斷嘗試重連等情況,這樣不能有效的快取,嚴重情況下會導致觀眾端視訊無法觀看。

RTMP累積延遲

此延遲只發生在RTMP協議中

RTMP有個弱點就是累積誤差,原因是RTMP基於TCP,而TCP不會丟包,(可能丟包,但是利用TCP的重傳機制避免)。

所以當網路狀態差時,伺服器會將包快取起來,導致累積的延遲;

待網路狀況好了,就一起發給客戶端。

這個的對策就是,當客戶端的緩衝區很大,就斷開重連。

GOP-Cache

影象群組Group opictures,GOP)

原理比較複雜,這裡就不班門弄斧了,具體可以Google

RTMP延遲

圖片來自:https://www.processon.com/view/56ebb341e4b01c9aeb5f137f

看完上圖你大概就能明白了,rtmp的延遲是和gop掛鉤的。

那麼,為什麼rtsp延遲會比rtmp低呢?因為,它是精確控制的,可以跳出這個以gop組為單位的控制。

視訊基本屬性

幀率(frame rate)

幀指的是碼流中的單張畫面,幀率指單位時間內碼流的幀數,單位fps(frame per second)。我們看到的視訊是由一幀幀的畫面,也就是一張張的圖片構成;如果一秒鐘跑過去的圖片有24張,幀率就是24幀/秒(fps);只有8張,幀率就是8幀/秒(fps);幀率越大,畫面就越流暢,當然大到一定程度,也不需要過大了,一方面肉眼也看不出有毛區別,另一方面電腦吃不消啊!

 

常見幀率

電影:23.976fps

電視(PAL):25fps

電視(NTSC):29.97fps

CRT顯示器:60Hz-85Hz

液晶顯示器:60Hz-75Hz

3D顯示器: 120Hz

解析度(resolution)

解析度指的是畫面的尺寸大小,解析度越高,影象越大。

一般的,在位元速率一定的情況下,解析度越高,視訊質量越差。

解析度有影象解析度與顯示解析度兩種,影象解析度指影象的尺寸大小,顯示解析度指螢幕解析度。

對於視訊而言,有一些固定尺寸的解析度標準,如D1(720×576)、4CIF(704×576)、VGA(640×480)、SVGA(800×600)、VXGA(1600×1200)等,後來對於固定比例(16:9)的畫面,解析度的的表示方法為縱向高度加掃描方式,如720P(1280×720,逐行掃描)、1080P(1920×1080,逐行掃描)、1080I(1920×1080,隔行掃描),再到後面,使用橫向畫素描述,如2K(2048×1536或2560×1440或2560×1600)、4K(4096×2160或3840×2160)、8K(7680×4320)。

位元速率(bit rate)

位元速率即位元率,指單位時間內產生的資料位,單位bps(bit per second),1Mbps=1024kbps=1048576bps。一般的,解析度一定的情況下,位元速率越高,視訊質量越好。

(*注意bps與B/s的區別,1B/s=8bps。)

通常,720P的碼流位元速率在2~4Mbps左右,1080P的碼流位元速率在4~8Mbps左右,對於使用者來說則是寬頻要求,要看720P的視訊需要至少2M的頻寬,要看1080P的視訊需要至少4M的頻寬,當前國內的網路環境下,上下行速率不對等,如果主播要使用高清視訊,還得確保主播上行頻寬足夠。

編碼方式

平常我們總在想,如何讓視訊檔案更小,讓視訊更清晰呢?答案就在位元速率上,對位元速率進行處理,就叫做編碼方式,一般有CBR/ABR/VBR三種方式.

 

CBR全稱constant bitrate,意思是固定位元速率,就是在整個視訊當中,位元速率固定不變;

VBR全稱Variable Bitrate,意為可變位元速率。其實在視訊當中,畫面內容越豐富,所需位元速率越高,成像質量也會越好,畫面內容不怎麼豐富的地方用高位元速率就是浪費,所以可變位元速率根據畫面內容的豐富程度自動調節,保證成像質量的同時,讓檔案變得更小。所以要讓視訊檔案更小,內容更清晰,採用VBR的編碼方式,並設定科學的數值,就是解決問題的關鍵。

ABR全稱average bitrate ,意為平均位元速率,是一種介於CBR和VBR之間的折中方式。

Codec 視訊編碼方式

其中,MPEG-1的編碼用於老VCD,MPEG-2的編碼用於DVD,之後的MPEG-4被用於更多更廣泛的平臺,這裡的MPEG-4就是傳說中的MP4;

另外呢,還有一個叫做國際電傳視訊聯盟(ITU)主導的另一套編碼方式,稱為H.26X系列,之後與MPEG合作弄出了H.264編碼方式,成為如今最熱門的編碼方式。

Container format視訊封裝格式

參考:https://en.wikipedia.org/wiki/Comparison_of_video_container_formats

主要封裝格式一覽

名稱

推出機構

流媒體

支援的視訊編碼

支援的音訊編碼

目前使用領域

AVI

Microsoft Inc.

不支援

幾乎所有格式

幾乎所有格式

BT下載影視

MP4

MPEG

支援

MPEG-2, MPEG-4, H.264, H.263等

AAC, MPEG-1 Layers I, II, III, AC-3等

網際網路視訊網站

TS

MPEG

支援

MPEG-1, MPEG-2, MPEG-4, H.264

MPEG-1 Layers I, II, III, AAC,

IPTV,數字電視

FLV

Adobe Inc.

支援

Sorenson, VP6, H.264

MP3, ADPCM, Linear PCM, AAC等

網際網路視訊網站

MKV

CoreCodec Inc.

支援

幾乎所有格式

幾乎所有格式

網際網路視訊網站

RMVB

Real Networks Inc.

支援

RealVideo 8, 9, 10

AAC, Cook Codec, RealAudio Lossless

BT下載影視

 

如何降低延遲時間

參考:

FFEMPEG方面

wiki:StreamingGuide

https://trac.ffmpeg.org/wiki/StreamingGuide

Low-Latency Live Streaming your Desktop using ffmpeg

http://fomori.org/blog/?p=1213

ffmpeg的轉碼延時測試與設定優化

https://blog.csdn.net/fireroll/article/details/51902018

FFmpeg推流延遲10秒問題記錄

https://blog.csdn.net/vanjoge/article/details/79545490

ffplay播放視訊源延時的引數設定

https://blog.csdn.net/cai6811376/article/details/52637158

Web直播系列4——ffmpeg實時推流+nginx負載均衡降低直播延時_1

https://blog.csdn.net/zzhang_12/article/details/79798027

ffmpeg拉流rtmp音訊實時資料有延時的解決方法

https://blog.csdn.net/a1317338022/article/details/78226834

如何實現1080P延遲低於500ms的實時超清直播傳輸技術

http://windrunnerlihuan.com/2016/09/18/%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B01080P%E5%BB%B6%E8%BF%9F%E4%BD%8E%E4%BA%8E500ms%E7%9A%84%E5%AE%9E%E6%97%B6%E8%B6%85%E6%B8%85%E7%9B%B4%E6%92%AD%E4%BC%A0%E8%BE%93%E6%8A%80%E6%9C%AF/

FFMPEG引數說明

參考:

https://blog.csdn.net/leixiaohua1020/article/details/12751349

https://trac.ffmpeg.org/wiki/Encode/H.264

主要引數

  • -i——設定輸入檔名。
  • -f——設定輸出格式。
  • -y——若輸出檔案已存在時則覆蓋檔案。
  • -fs——超過指定的檔案大小時則結束轉換。
  • -t——指定輸出檔案的持續時間,以秒為單位。
  • -ss——從指定時間開始轉換,以秒為單位。
  • -t從-ss時間開始轉換(如-ss 00:00:01.00 -t 00:00:10.00即從00:00:01.00開始到00:00:11.00)。
  • -title——設定標題。
  • -timestamp——設定時間戳。
  • -vsync——增減Frame使影音同步。
  • -c——指定輸出檔案的編碼。
  • -metadata——更改輸出檔案的元資料
  • -help——檢視幫助資訊。

視訊引數

  • -b:v——設定視訊流量,預設為200Kbit/秒。(單位請引用下方注意事項
  • -r——設定幀率值,預設為25。
  • -s——設定畫面的寬與高。
  • -aspect——設定畫面的比例。
  • -vn——不處理視訊,於僅針對聲音做處理時使用。
  • -vcodec( -c:v )——設定視訊視訊編解碼器,未設定時則使用與輸入檔案相同之編解碼器。

聲音引數

  • -b:a——設定每Channel(最近的SVN版為所有Channel的總合)的流量。(單位請引用下方注意事項
  • -ar——設定取樣率。
  • -ac——設定聲音的Channel數。
  • -acodec ( -c:a ) ——設定聲音編解碼器,未設定時與視訊相同,使用與輸入檔案相同之編解碼器。
  • -an——不處理聲音,於僅針對視訊做處理時使用。
  • -vol——設定音量大小,256為標準音量。(要設定成兩倍音量時則輸入512,依此類推。)

注意事項

  • 以-b:v及-b:a首選項流量時,根據使用的ffmpeg版本,須注意單位會有kbits/sec與bits/sec的不同。(可用ffmpeg -h顯示說明來確認單位。)

例如,單位為bits/sec的情況時,欲指定流量64kbps時需輸入 -b:a 64k;單位為kbits/sec的情況時則需輸入 -b:a 64。

  • 以-acodec及-vcodec所指定的編解碼器名稱,會根據使用的ffmpeg版本而有所不同。例如使用AAC編解碼器時,會有輸入aac與libfaac的情況。此外,編解碼器有分為僅供解碼時使用與僅供編碼時使用,因此一定要利用ffmpeg -formats確認輸入的編解碼器是否能運作。

直播中常見引數

-preset

按編碼速度的內建引數,內建的編碼設定有:

  1. ultrafast
  2. superfast
  3. veryfast
  4. faster
  5. fast
  6. medium
  7. slow
  8. slower
  9. veryslow
  10. placebo

按快到慢排列,預設為medium級,當然越慢效果越好,但是體積會增大,一般最求高質量用veryslow就夠了。

-tune

按不同的源或者不用的應用場景的內建引數

  1. film:電影、真人型別
  2. animation:動畫
  3. grain:需要保留大量的grain時用
  4. stillimage:靜態影象編碼時使用
  5. psnr:為提高psnr做了優化的引數
  6. ssim:為提高ssim做了優化的引數
  7. fastdecode:可以快速解碼的引數
  8. zerolatency:零延遲,用在需要非常低的延遲的情況下,比如電視電話會議的編碼

在命令列中輸入:ffmpeg -h encoder=libx264

參考:

https://my.oschina.net/u/3733374/blog/1581609

https://www.zhihu.com/question/23651189

https://blog.csdn.net/leixiaohua1020/article/details/18893769

https://sdk.cn/news/5556