直播與點播之三_測試、理解

IMchg發表於2020-11-07

以下理解均為猜測,未檢視原始碼驗證;待檢視原始碼後核實【應該是不會看的】;

注意:下文中Nginx-RTMP、Nginx-HTTP-FLV-Module其實均指的是Nginx-HTTP-FLV-Module

一 所謂的推流和拉流到底是怎麼回事?

  1. 是像SMTP和POP3那樣,存在 主動推+被動 和 主動拉+被動 兩種互動方式?還是隻是為網路上了方便理解隨口一說?網路上未找到明確講解。
  2. 如果確實分主動推、主動拉兩種模式,那麼:直播/點播整個架構中的各個模組間,分別是以何種方式在互動?具體來說:
    (1) 攝像頭是主動推,還是被動輸出?
    (2) FFmpeg輸入是主動拉,還是被動接收,輸出是主動推,還是被動輸出?
    (3) Nginx-RTMP輸入是主動拉,還是被動接收?Nginx-RTMP輸出是主動推,還是被動輸出?
    (4) 瀏覽器、播放器輸入是主動拉,還是被動接收?

個人理解,確實分主動推和主動拉兩種模式。並據此對以下現象做出解釋:

1.1 測試一:FFmpeg 推和拉

現象:

  1. 不啟動Nginx-RTMP,FFmpeg將RTSP轉為RTMP推流,直接報錯,“無法建立連線”;
  2. 不啟動Nginx-RTMP,FFmpeg將RTSP轉為RTMP推流,PotPlayer拉流,不能播放;
  3. 啟動Nginx-RTMP,FFmpeg將RTSP轉為RTMP推流,PotPlayer拉流,能接收播放;

猜想:

  1. FFmpeg輸出是主動推,輸出協議可以是RTMP、HTTP等,且輸出時必須要先有接收方監聽埠,接收資料。接收方要是被動。【相當於用於寫檔案的程式】
  2. PotPlayer接收是主動拉,輸入可以是RTMP、HTTP等,且輸入時必須要先有輸出方提供資料。輸出方要是被動。【相當於用於讀檔案的程式】
  3. Nginx-RTMP起快取資料的作用,可以被動接收和被動輸出。【相當於檔案,被讀和被寫】

解釋: 根據猜想對現象進行解釋

  1. 現象1中:不存在被動接收方(檔案),推流無法主動輸出(寫檔案);
  2. 現象2中:FFmpeg與Potplayer不存在被動方,因此無法連線;【相當於一個寫程式、一個讀程式,二者無法直接進行資料交換】
  3. 現象3中:Nginx-RTMP先是作為被動方接收FFmpeg的RTMP流(一個程式寫入檔案),然後作為被動方提供RTMP流,PotPlayer主動從Nginx-RTMP中拉取資料(一個程式讀取檔案)。

1.2 測試二:瀏覽器 拉流

對之前提到的websock直播進行分析
現象:

  1. 不啟動websocket-relay,FFmpeg將RTSP轉為HTTP推流,直接報錯,“無法建立連線”;
  2. 不啟動websocket-relay,FFmpeg將RTSP轉為HTTP推流,瀏覽器請求,無法播放;
  3. 啟動websocket-relay,FFmpeg將RTSP轉為HTTP推流,瀏覽器請求,可以播放;
  4. 不啟動websocket-relay、啟動nginx,FFmpeg將RTSP轉為HTTP推流,直接報錯,“無法建立連線”。

猜想:

  1. 瀏覽器輸入是主動拉;
  2. websocket-relay是起資料快取的作用(相當於Nginx-HTTP-FLV,只不過由收RTMP/發HTTP換成了收HTTP/發WS);
  3. 原生nginx不能接收http請求並存為檔案;

解釋: 根據猜想對現象進行解釋

  1. 現象1、2、3中:可以檢視websocket-relay原始碼,HttpServer接收客戶端(FFmpeg)的請求,WebsocketServer與瀏覽器建立連線;HttpServer讀取請求中的資料,交由WebsocketServer傳送;【HTTP協議,請求方是主動方】
  2. 雖然FFmpeg可以直接輸出HTTP,但是原生Nginx中沒有接收HTTP請求快取資料的功能,因此不能接收FFmpeg推送的HTTP流。而nginx-http-flv-module不支援接收HTTP視訊流,或者說只支援以RTMP接收視訊流。

1.3 大膽猜測

  1. 攝像頭被動提供視訊流;
  2. 播放器主動拉流;
  3. FFmpeg主動拉流、主動推流;
  4. Nginx被動接收、被動輸出;

這樣FFmpeg可和攝像頭直連,而FFmpeg和播放器之間必須要有一個快取資料的部件,也就是視訊伺服器,視訊伺服器被動接收、被動提供,相當於一個檔案。

二 jsmpeg方案為啥比http-flv方案延遲小那麼多?

兩種方案傳輸協議的差異:
HTTP方案中,FFmpeg將RTSP轉為RTMP,Nginx-RTMP將RTMP轉為HTTP。
Jsmpeg方案中,FFmpeg將RTSP轉為HTTP,websocket-relay將HTTP轉為Websocket。
這麼看的話,Jsmpeg方案中不轉Websocket,直接將HTTP視訊流發到瀏覽器可以嗎?感覺可以啊,不知道為啥不這麼做啊。
【也就是自己寫一個接收HTTP上傳的視訊流(來自FFmpeg),快取後以HTTP轉發】

兩種方案FFmpeg處理的差異:
HTTP-FLV方案中,FFmpeg以RTSP協議接收,以RTMP協議轉發,用FLV封裝,用H264+AAC編碼;
Jsmpeg方案中,FFmpeg用RTSP協議接收,用HTTP協議轉發,用MPEG-TS封裝,用mpeg1video編碼。

Websocket協議和HTTP協議傳輸效率有差異?RTSP轉RTMP和轉HTTP效率有差異?FLV和MPEG-TS封裝效率有差異?H264和mpeg1video編碼效率有差異?進行以下試驗。

2.1 是Websocket協議比HTTP協議傳輸更快嗎?

使用Node-Media-Server的方案,用Websocket-FLV。
處理流程:FFmpeg將RTSP流轉為RTMP流【用RTSP協議接收,RTMP協議轉發,用FLV封裝,H264+AAC編碼】,然後通過NMS伺服器推送到前端。
結果:延遲與HTTP-FLV差不多。
可見,不是傳輸協議差異引起的。

2.2 是RTSP轉RTMP引起的嗎?

能夠用FFmpeg將RTSP轉HTTP,視訊伺服器接收後再用HTTP傳送到瀏覽器嗎?Nginx-RTMP不支援,沒有現成的工具。
既然,FFmpeg能夠直接將RTSP流轉為HTTP流,為啥HTTP-FLV方案中還要先轉為RTMP?這個是nginx-rtmp模組本身限制,nginx-rtmp模組輸入視訊流只能是RTMP的。

2.3 是封裝或編解碼效率問題嗎?

能夠讓Nginx-http-flv用HTTP協議傳MPEG2-TS封裝、video1mpeg編碼的視訊流,瀏覽器用jsmpeg解碼嗎?不行,和上面原因一樣,這個是nginx-rtmp模組本身限制,nginx-rtmp模組輸入視訊流只能是RTMP協議的,而RTMP只支援FLV封裝。

三 瀏覽器直播、點播有什麼限制?

從瀏覽器端來看,播放主要限制有三點:對協議的支援、對封裝格式的支援、對解碼格式的支援。

注意:協議本來就和封裝格式存在關聯,如:RTMP只支援FLV封裝格式,HTTP、Websocket應是支援所有封裝格式。

3.1 瀏覽器本身支援的協議有哪些?

HTTP、Websocket;所以要是用RTMP、RTSP傳輸,必然要在瀏覽器中加上外掛,或者js庫,如:Flash播放器外掛。(Flash播放器也只是支援RTMP,還沒看到瀏覽器直接接收RTSP的例子)

3.2 瀏覽器(H5)本身支援的封裝格式有哪些?

MPEG4、WebM,OOG;所以要是用FLV封裝必然要在瀏覽器中加上外掛,或者js庫,如:flvjs。
【咦,按照這個分析,flvjs只說能夠處理FLV封裝,似乎沒說過支援RTMP流啊,之前沒注意這個問題】

3.3 瀏覽器(H5)本身支援的編碼格式有哪些?

https://www.w3school.com.cn/html5/html_5_video.asp

就MPEG4來說,H264+AAC編碼,所以要是用mpeg1video編碼,必然要在瀏覽器中加上外掛,或者js庫,如:jsmpeg。

四 音視訊的編碼格式、封裝格式、副檔名

要學FFmpeg先得弄清楚音視訊檔案的編碼格式、封裝格式、副檔名概念。在這個場景下,檔案格式的含義與日常語境下的不同。這裡,檔案格式!=副檔名。檔案格式指的是檔案的封裝格式,檔案格式也被叫做容器格式。

注意:音視訊處理中視乎從來沒有關注過檔案的副檔名

編碼格式、封裝格式、副檔名

4.1 概念

編碼指的是對取樣得到的音訊、影像資料進行壓縮,得到音訊、視訊;
封裝指的是對音訊+視訊進行封裝打包;
副檔名是將打包後的檔案與電腦上的播放器關聯;

4.2 關係

編碼方式有多種、封裝方式有多種、副檔名有多種
同樣的採集資料可用不同的方式進行編碼,編碼方式就是編碼名
同樣編碼的資料可用不同的方式進行封裝,封裝方式就是封裝名
同樣封裝的資料可用不同的方式進行命名,命名就是副檔名
但是相應地,封裝格式只支援特定的編碼方式,擴充名只支援特定的封裝格式。
是多對多,又不是任意的多對多。

4.3 疑問

由於編碼、封裝、副檔名都是由對應組織負責的,命名方式與組織名相關;加上日常對格式的稱呼不嚴謹,如果不仔細甄別,乍一看可能覺得:一個名字既是視訊編碼名、又是音訊編碼名、還是封裝名、還是副檔名。

如:
組織名:MPEG
視訊編碼格式:MPEG2
音訊編碼格式:MPEG-2 AAC
封裝格式:MPEG-2
視訊檔案格式:MPEG

部落格中常見的TS,指的是MPEG2-TS,是封裝格式。

https://blog.csdn.net/leixiaohua1020/article/details/18893769
http://einverne.github.io/post/2018/10/webm.html
https://blog.csdn.net/wangzekun_wolf/article/details/89532912

五 jsmpeg方案錄製問題

直播與點播之二中講到了jsmpeg方案無法錄製,而基於Nginx的方案能夠錄製,那將Nginx作為websocket-relay與瀏覽器之間的代理,可以實現錄製嗎?
實現:
一:Nginx實現Websocket代理:可以實現
二:依然無法錄製,Nginx-RTMP方案實現錄製是基與nginx-rtmp-module的,nginx本身無法邊傳輸邊拷貝到伺服器上,那通過nginx呼叫ffmpeg可行嗎?沒找到nginx呼叫外部應用的方法,nginx-rtmp-module中倒是有。 錄製是nginx-rtmp-module的功能,且只支援RTMP輸入流。

相關文章