MacBook Pro に付いているカメラ (720p FaceTime HDカメラ)、あるいは USB で Mac に接続した Web カメラの映像を FFmpeg でキャプチャしながらリアルタイムに HTTP Live Streming (HLS) で配信できるようにしてみます。ビデオのフォーマットは HEVC/H.265 です。ビデオファイルのコンテナは fMP4 です。
私の環境
MacBook Pro (15-inch, 2016)
- macOS Catalina 10.15.6
- 2.6GHz クアッドコア Inte Core i7
- メモリ 16GB
- グラフィックス Radeon Pro 450 2GB, Intel HD Graphics 530 1536MB
- Logicool HD Webcam C910
- FFmpeg 4.3.1
FFmpeg は Homebrew でインストールした FFmpeg 4.3.1 です。
macOS と FFmpeg で HEVC/H.265 ハードウェアエンコードを行うための設定は下記の投稿で紹介しています。
カメラの番号の確認
macOS で認識されているカメラの番号を、ビデオとオーディオについて確認してみます。
下記のコマンドで確認することができます。Web カメラを接続した状態では、MacBook Pro に付いているカメラの番号はビデオは 0、オーディオは 0 でした。また、USB で接続した Web カメラの番号はビデオは 1、オーディオは 0 でした。
% ffmpeg -f avfoundation -list_devices true -i ""
ffmpeg version 4.3.1
...
[AVFoundation indev @ 0x7f886842aac0] AVFoundation video devices:
[AVFoundation indev @ 0x7f886842aac0] [0] FaceTime HDカメラ(内蔵)
[AVFoundation indev @ 0x7f886842aac0] [1] USBカメラ #2
[AVFoundation indev @ 0x7f886842aac0] [2] Capture screen 0
[AVFoundation indev @ 0x7f886842aac0] [3] Capture screen 1
[AVFoundation indev @ 0x7f886842aac0] AVFoundation audio devices:
[AVFoundation indev @ 0x7f886842aac0] [0] Unknown USB Audio Device
[AVFoundation indev @ 0x7f886842aac0] [1] Built-in Microphone
FFmpeg のコマンド
私の環境では、MacBook Pro に付いているカメラの番号は、ビデオは 0、オーディオは 1 でした。よって、FFmpeg の avfoundation での設定は “0:1” となります。
下記のコマンドを実行すると、最終行の /path/to/ に M3U8 プレイリストファイルと fMP4 ファイルが作成されていきます。
/path/to/ のパスを Web サーバーで公開できるパスに設定しておけば、MacBook Pro のカメラのキャプチャを HLS の HEVC/H.265 に対応したクライアントで再生することができるでしょう。
ffmpeg \
-f avfoundation \
-framerate 30 \
-s 1280x720 \
-pix_fmt yuyv422 \
-i "0:1" \
-vcodec hevc_videotoolbox \
-tag:v hvc1 \
-vf yadif \
-g 10 \
-b:v 2000k \
-acodec aac \
-ab 128k \
-ac 2 \
-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_videotoolbox) に変換されていることがわかります。また、変換速度も 1x であり、リアルタイムにエンコードできていることもわかります。さらに、fMP4 の m4s ファイルもシーケンス番号が増えながら作成されていることがわかります。
しかし、私の環境では映像と音が若干ずれていました。解決方法はわかりません。
Input #0, avfoundation, from '0:0':
Duration: N/A, start: 37014.814580, bitrate: N/A
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 30 tbr, 1000k tbn, 1000k tbc
Stream #0:1: Audio: pcm_f32le, 44100 Hz, stereo, flt, 2822 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> hevc (hevc_videotoolbox))
Stream #0:1 -> #0:1 (pcm_f32le (native) -> aac (native))
Press [q] to stop, [?] for help
[hls @ 0x7fb91c057c00] Opening '/tmp/init.mp4' for writing
Output #0, hls, to '/tmp/hls.m3u8':
Metadata:
encoder : Lavf58.45.100
Stream #0:0: Video: hevc (hevc_videotoolbox) (hvc1 / 0x31637668), yuv420p, 1280x720, q=2-31, 2000 kb/s, 30 fps, 15360 tbn, 30 tbc
Metadata:
encoder : Lavc58.91.100 hevc_videotoolbox
Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc58.91.100 aac
[hls @ 0x7fb91c057c00] Opening '/tmp/hls0.m4s' for writingte=N/A dup=74 drop=0 speed= 1.2x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x7fb91c057c00] Opening '/tmp/hls1.m4s' for writingte=N/A dup=74 drop=0 speed=1.08x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x7fb91c057c00] Opening '/tmp/hls2.m4s' for writingte=N/A dup=74 drop=0 speed=1.05x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x7fb91c057c00] Opening '/tmp/hls3.m4s' for writingte=N/A dup=74 drop=0 speed=1.04x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x7fb91c057c00] Opening '/tmp/hls4.m4s' for writingte=N/A dup=74 drop=0 speed=1.03x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
[hls @ 0x7fb91c057c00] Opening '/tmp/hls5.m4s' for writingte=N/A dup=74 drop=0 speed=1.03x
[hls @ 0x7fb91c057c00] Opening '/tmp/hls.m3u8.tmp' for writing
frame= 789 fps= 31 q=-0.0 Lsize=N/A time=00:00:26.33 bitrate=N/A dup=74 drop=0 speed=1.03x