FFMPEG 進行攝影機串流與架設 RTSP Server

前一陣子工作上有對 webcam 做串流的需求,平台當然是在 Linux 上,用的軟體是 ffmpeg + ffserver。之前對 ffmpeg 使用,都是有點亂拼亂湊,上網找範例,能動就好了。但後來隨著應用變的更複雜,這樣也就混不下去了,因此也對 ffmpeg 的語法研究了一翻。

這邊還是推荐從官方的文件開始,耐著性子看半小時相信一定會有比較好的瞭解。這邊就講我最大的收獲就好了,命令列參數的原則如下:

  1. -i 就是指定輸入裝置
  2. 不是參數也不是輸入裝置,就會被認為是輸出裝置。
  3. 所有的參數指定,會套用在下一個指定的輸入裝置或輸出裝置。

ffmpeg 的簡單自我反醒就這樣,下面就開始介紹如何用 FFMPEG 套件的 FFServer,做 RTSP 的串流。

FFSERVER

ffserver 是 ffmpeg 套件裡的 media server,不過在2018-01-06後的新版已不在支援 ffserver 了。若還要使用的話,就要用比較舊的 3.4 branch release。由於多媒體這種東西演進不算快,所以用  3.4 基本上還算穩定。

這邊編碼的例子都是用 mpeg4 這個 codec 來進行,主要是 mpeg4 的編碼速度比 h264/h265 快非常多,在一些弱弱的機器甚至是嵌入式系統也能跑的動。當然缺點就是畫質較差,流量偏大。有想試試看的人,也可以指定 codec 為 libx264/libx265 來看看。

ffserver 編譯

本來以為自己編 ffmpeg 會很麻煩,不過後來真實跑起來發現還蠻順的,相依的 library 都已包含在套原始碼裡面,基本上是 configure & make 就可以了。

或者用 ARM 的 toolchain 也可以編譯成功

編譯後即可看到 ffmpeg 與 ffserver 的執行檔了。

ffmpeg 與 ffserver

 

ffserver 設定為主的串流設定

FFMPEG 套件的串流,可以透過 ffserver 的設定檔,或者是由 ffmpeg 執行期的參數來決定。由於ffserver的參數與ffmpeg不同,而我學習的主要還是ffmpeg的用法,所以一直是由 ffmpeg 直接指定參數。下面僅列出曾經用過ffserver設定檔的例子給大家參考。

Feed 的部份,算是 ffmpeg 將影像原始資料傳遞給 ffserver的設定。而 Stream 的部份,則是根據不同的 URL,ffserver 會根據設定內容的不同,將影像編碼再傳給觀看用戶。

將上面的檔案存成 /tmp/ffserver.conf,然後執行 ./ffserver -f /tmp/ffserver.conf &,這時 ffserver 就會等待原始資料進來。此時,我們再執行 ffmpeg 將原始影像資料從 webcam 抓出來,並傳遞給 ffserver,就會開始編碼。

ffmpeg 最後面的 http:// 的部份,即是資料輸出的網址,也就是剛剛 ffserver 設定檔內指定的 HttpPort Feed。此時再透過 VLC 或 ffplay 就可以播放 RTSP 的資料,以 ffplay 為例的話。播放串流 test.mp4,就輸入命令 ffplay rtsp://xxx.xxx.xx.xx:5554/test.mp4。而播放 test2.mp4,就輸入 ffplay rtsp://xxx.xxx.xx.xx:5554/test2.mp4。

5554是ffserver內指定的 RtspPort,而 test.mp4 與 test2.mp4 則是裡面的 Stream 部份。這兩個並不是真的檔案,而只是一個名字。ffserver 會依據其設定,來即時轉碼做串流。所以觀看 test.mp4 會是 640×480 的大小,而 test2.mp4 則是 160×120。

ffmpeg 設定為主的串流

以 ffmpeg 參數為主的 ffserver 設定檔,前面 HttpPort 和 RtspPort 參數一樣。Feed 從一個變成了兩個,因為ffserver不再進行轉碼,Feed 會直接儲存轉碼好的資料,所以需要分成2個。而兩個 Stream, preview 與 live, 內不再指定格式,而分別指定不同的 Feed 來提供影像給用戶。

ffserver 的參數簡化了,ffmpeg 的自然就會雜一點。這裡會用一個實際使用的例子來解說,所以會複雜一點。這些指令做到了下列功能:

  1. 從 webcam 以FPS=10 抓取1280×720原始圖檔 (YUV) (行1)
  2. 產生一個 160×120 FPS=10 的 MPEG4 串流餵給 feed1,編碼的速率指定為 100kbps (行2,3)
  3. 產生一個 1280×720 FPS=10 的 MPEG4 串流,編碼速率指定為 1000kbps,將這個串流傳到 feed2。並且,將這個串流的資料儲檔到/tmp/video%Y-%m%d_%H-%M-%s.mp4 (年月日_時分秒),以60秒為一個檔案。(行4,5)

行4有個 -override_ffserver 就是指定要使用 ffmpeg 的參數來串流,而非 ffserver 的。

 

播放的命則與之前類似

其它的串流方法

從 Hardware Encoder 截取串流

有工業用的 WEBCAM 支援硬體編碼的 H264, 一般常市面上的則支援 MJPG的硬體編碼。透過直接截取,不再重新轉碼,可以省下 大量的CPU 運算量。

其中 input_format 後面指定了 mjpeg ,有的也支援 h264 / h265。但到 2021 年為止在 V4L2 Linux API h265截碼不是做的很完整, h264 支援會較好。 要看自己的 webcam 指援哪些編碼,可以下達 v4l2-ctl –list-formats

列出支援的格式

 

直接傳遞 RTP 串流

若要使用簡單一點的點對點傳輸,可以直接把編碼後的資料,傳給指定的 IP:Port,這樣就不用架設 RTSP Server (ffserver的部份)了。下面會同時抓取聲音與影像,聲音裝置的部份,可以讀取 /proc/asound/cards 來判定有哪些聲音輸入。

列出音效裝置

從上圖看到有兩個裝置,分別為 「MID」與「C615」。這邊選用 C615來截取聲音,若要用MID則將下面範例的字取代掉就好。若使用 -ac 1 會看到錯誤訊息 「cannot set channel count to 1」,這是因為它只支援雙聲道,有的卡會只支援單聲道。在 “-ac 1” 的部份,可以試試看1 or 2,應該有一個會成功。

下達上面的命令就開始串流了,然後在 Windows 端 (IP: 192.168.11.2) 開啟 VLC播放器,使用「媒體」–> 「開啟網路串流」網址輸入 rtp://@1234。就可以開始播放該串流了,第一次開啟會提示允許防火牆,記得選則允許。

結語

ffmpeg 其實是一個蠻好玩又強大的工具的,工作上可以來做這些串流,截圖存檔的。個人生活上,我也拿來將影像轉碼成 h265 來縮小檔案大小,有時甚至可以達到h264 1/10 的大小。當然這是因為在畫質上有點損失,加上一般相機都把編碼率調超高,才會有這種90%減少的可怕改進。

Leave a Reply