Linux 下的視訊裝置遠端測試
好些年前 DR 曾試驗過以 ffserver 為基礎的 Linux 直播方案。ffserver 是 FFmpeg 專案的一個附屬程式,其用途是建立一個可接收及輸出媒體串流的多媒體伺服器。當時 DR 的作法是在一部 Linux 主機上安裝一張影音擷取卡,然後用 ffserver 起建一個 HTTP 伺服器。再透過 ffmpeg 指令,將擷取卡的資料流直接送給本機的接收 URL ,而外部客戶端的媒體播放器只要開啟主機 HTTP 位址就能夠播放串流。
不過如今一般來說,多半會利用 YouTube 這類平台來作為直播用的媒體伺服器,自建伺服器的需求並不大;以及另一方面 FFmpeg 也已停止對 ffserver 的維護,並且在 4.0 版後被徹底移除,所以過往所研究的方案已無實際的可用性。然而倘若連接視訊裝置的電腦,並不在手邊可觸及之處。但仍需要測試裝置是否正常,因此得遠端操作,且無須透過外部的媒體伺服器。那麼在此情境下,則可以藉助 VLC 來便利地建立伺服器以進行測試。
本文是在 Fedora 31 下操作,使用的視訊裝置為 Blackmagic Web Presenter。它本質上是一款多媒體轉碼盒,不過在作業系統裡是以網路攝影機(webcam)的形式運作,換言之,透過 UVC(USB Video Class)驅動程式即可使用。
當 Linux 內核在偵測到諸如網路攝影機等擷取設備後,會進一步分拆成視訊及音訊擷取裝置,分別由 V4L2(Video4Linux 2)及 ALSA 來管理。在本機環境下,使用者權限可以直接存取這類裝置;然而在遠端環境(SSH)下,使用者必須明確地加入到 video 及 audio 群組才能夠存取。對此,可執行以下指令,將特定的使用者加入到群組裡,重新登入後即生效:
- sudo usermod -aG video <username>
- sudo usermod -aG audio <username>
使用以下指令查看 Web Presenter 支援的視訊輸出格式:
- ffmpeg -f v4l2 -list_formats all -i /dev/video0
其中的關鍵資訊列舉如下,表示該視訊裝置有 yuyv422 及 mjpeg 兩種輸出格式,並支援不同的解析度:
[video4linux2,v4l2 @ 0x55b222b49e00] Raw : yuyv422 : YUYV 4:2:2 : 640x480 320x240 640x480
[video4linux2,v4l2 @ 0x55b222b49e00] Compressed: mjpeg : Motion-JPEG : 1280x720 800x600 640x480 1280x720
接著,可使用以下指令列出當前系統上所有的音訊擷取裝置:
- arecord -l
在輸出訊息裡,下列資訊即表示 Web Presenter 的音訊擷取裝置,其編號為「2,0」,也就是 card 2 中的 device 0:
card 2: Presenter [Blackmagic Web Presenter], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
然後便根據以上步驟所蒐集的資訊,為 ffmpeg 指令加入相應的來源設定,並轉碼為 H.264/AAC 串流,再輸送給 VLC:
- ffmpeg -f v4l2 -thread_queue_size 8192 -video_size 1280x720 -input_format mjpeg -i /dev/video0 -f alsa -thread_queue_size 8192 -ac 2 -i hw:2,0 -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -pix_fmt yuvj420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv -|cvlc stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=0.0.0.0:8080}'
前述指令會讓 VLC 起建一個 HTTP 伺服器,監聽連接埠為 8080(別忘了防火牆得放行相應的規則),而客戶端使用 http://<主機 IP>:8080 即能夠播放串流。
或者,不經過 ffmpeg 轉碼、也不包含音訊,直接以 VLC 擷取視訊並建立 HTTP 伺服器的指令如下:
- cvlc v4l2:///dev/video0:chroma=mjpg:width=1280:height=720 --sout '#standard{access=http,mux=ts,dst=0.0.0.0:8080}'