NVIDIA GeForce のビデオカードを接続した Ubuntu 20.04 に Web カメラを接続し、その映像とマイクの音声を FFmpeg でキャプチャしながらリアルタイムに HTTP Live Streming (HLS) で配信できるようにしてみます。ビデオのフォーマットは HEVC/H.265 です。ビデオファイルのコンテナは fMP4 です。
私の環境
- Ubuntu 20.04
- NVIDIA GeForce GTX-1050
- Logicool HD Webcam C910
- FFmpeg 4.3.1
FFmpeg はソースコードからビルドしてインストールした FFmpeg 4.3.1 です。
Ubuntu と NVIDIA GeForce GTX-1050 と FFmpeg で HEVC/H.265 ハードウェアエンコードを行うための設定は下記の投稿で紹介しています。
Web カメラのオーディオデバイス番号の固定化
Ubuntu 20.04 に Web カメラを接続する場合、接続する度に Web カメラのマイクのオーディオデバイス番号が変更されることがあります。それを防ぐために、その番号を固定化します。
固定化の方法については、下記の投稿で紹介しています。
ここでは、Web カメラのマイクのオーディオデバイス番号を
- card は 0
- device は 0
としました。つまり、FFmpeg の i オプションで hw:0,0 あるいは default として設定することができます。
FFmpeg のコマンド
Web カメラのビデオデバイス名は /dev/video0 です。
下記のコマンドを実行すると、最終行の /path/to/ に M3U8 プレイリストファイルと fMP4 ファイルが作成されていきます。
/path/to/ のパスを Web サーバーで公開できるパスに設定しておけば、Web カメラのキャプチャを HLS の HEVC/H.265 に対応したクライアントで再生することができるでしょう。
ffmpeg \
-f video4linux2 \
-s 960x540 \
-i /dev/video0 \
-f alsa \
-ac 2 \
-i hw:0,0 \
-acodec aac \
-ab 128k \
-ar 44100 \
-s 960x540 \
-vcodec hevc_nvenc \
-tag:v hvc1 \
-vf yadif \
-g 10 \
-b:v 1600k \
-pix_fmt yuv420p \
-threads 1 \
-f hls \
-hls_segment_type fmp4 \
-hls_time 5 \
-hls_fmp4_init_filename init.mp4 \
/path/to/hls.m3u8
上記のコマンドを実行した際の FFmpeg のログは下記の通りです。ビデオが HEVC/H.265 (hevc (hevc_nvenc)) に変換されていることがわかります。また、変換速度も 1x であり、リアルタイムにエンコードできていることもわかります。さらに、fMP4 の m4s ファイルもシーケンス番号が増えながら作成されていることがわかります。
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 9 (Ubuntu 9.3.0-10ubuntu2)
configuration: --disable-shared --enable-static
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
[video4linux2,v4l2 @ 0x55b4329b4e00] The V4L2 driver changed the video from 960x540 to 960x544
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 486531.924850, bitrate: 167116 kb/s
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 960x544, 167116 kb/s, 20 fps, 20 tbr, 1000k tbn, 1000k tbc
Guessed Channel Layout for Input Stream #1.0 : stereo
Input #1, alsa, from 'hw:0,0':
Duration: N/A, start: 1596876680.787106, bitrate: 1024 kb/s
Stream #1:0: Audio: pcm_s16le, 32000 Hz, stereo, s16, 1024 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> hevc (hevc_nvenc))
Stream #1:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
[alsa @ 0x55b4329b8dc0] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
[hls @ 0x55b4329dbc80] Opening '/tmp/init.mp4' for writing
Output #0, hls, to '/tmp/hls.m3u8':
Metadata:
encoder : Lavf58.45.100
Stream #0:0: Video: hevc (hevc_nvenc) (Main) (hvc1 / 0x31637668), yuv420p, 960x540, q=-1--1, 1600 kb/s, 20 fps, 10240 tbn, 20 tbc
Metadata:
encoder : Lavc58.91.100 hevc_nvenc
Side data:
cpb: bitrate max/min/avg: 0/0/1600000 buffer size: 3200000 vbv_delay: N/A
Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc58.91.100 aac
[video4linux2,v4l2 @ 0x55b4329b4e00] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
[hls @ 0x55b4329dbc80] Opening '/tmp/hls0.m4s' for writingte=N/A dup=15 drop=0 speed=0.996x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
[mp4 @ 0x55b4330e9540] Application provided duration: -5 / timestamp: 222223 is out of range for mov/mp4 format
[hls @ 0x55b4329dbc80] Opening '/tmp/hls1.m4s' for writingte=N/A dup=15 drop=0 speed=0.998x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x55b4329dbc80] Opening '/tmp/hls2.m4s' for writingte=N/A dup=15 drop=0 speed=0.999x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
[mp4 @ 0x55b4330e9540] Application provided duration: -3 / timestamp: 662555 is out of range for mov/mp4 format
[hls @ 0x55b4329dbc80] Opening '/tmp/hls3.m4s' for writingte=N/A dup=15 drop=0 speed=0.999x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
[mp4 @ 0x55b4330e9540] Application provided duration: -2 / timestamp: 883737 is out of range for mov/mp4 format
[hls @ 0x55b4329dbc80] Opening '/tmp/hls4.m4s' for writingte=N/A dup=15 drop=0 speed= 1x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x55b4329dbc80] Opening '/tmp/hls5.m4s' for writingte=N/A dup=15 drop=0 speed=0.999x
[hls @ 0x55b4329dbc80] Opening '/tmp/hls.m3u8.tmp' for writing
frame= 658 fps= 20 q=25.0 size=N/A time=00:00:32.80 bitrate=N/A dup=15 drop=0 speed=0.999x
なお、-r 30 のようにフレームレートを設定するオプションを付けると、私の環境では著しくエンコード速度が落ちてしまい、リアルタイム配信をすることができませんでした。
また、Web カメラのマイクのチャンネルがステレオではない場合、-ac 2 を -ac 1 に変更する必要があります。