Creazy!

WEBエンジニア・ヤガーのテック・ガジェットブログ

ffmpeg RaspberryPi ガジェット 小技集

Raspberry Pi 4 Model B 8GBでライブ配信(1) USB接続のWEBカメラ映像をFFmpegで保存してみる

投稿日:


ブログご無沙汰しております。ヤガーです。

本業のWEB開発と並行して、リモートワーク推奨の影響でライブ配信などの需要が高まっており、以前よりイベントなどで配信をしていた関係で様々な形式でのライブ配信方法を検証していたりします。その中で観光地のライブカメラを検証する必要があったのですが、専用機種は数十万レベルの予算となりなかなか気軽に導入できるものではないため安い機材での自作ができないかと模索しておりました。VLOGなどの撮影用に購入したGoProに内蔵されているライブ配信機能にも期待して色々検証していたのですが、ライブカメラのように24時間365日稼働させるような安定感は出ないものと諦めました。今回は、廉価に手に入れられるRaspberry PiとWEBカメラの組み合わせでライブ配信の仕組みが構築できないか実験してみます。

実験手順を残していると結構文量が多くなるため、今回はとりあえずWEBカメラをつないで動画ファイルとしてローカル保存するまでをやってみます。

検証環境

– Raspberry Pi 4 Model B 8GB
– Raspberry Pi OS 64bit (Linux raspberrypi 5.10.92-v8+ #1514)
– ffmpeg version 4.3.3
– Logicool C270
– Logicool C920

直接関係ないですが、ホストマシンは

– Mac mini (M1, 2020)
– macOS Monterey 12.1

で操作しています。

かなり余談ですが、記事執筆時点で世界的なチップ不足により現在Raspberry Piの在庫もほとんど見つからないようです。本来は1万円くらいで購入できますが、Amazonなどで2〜3倍くらいに高騰している可能性がありますので気をつけてご購入ください。

Raspberry Pi 4のセットアップ

Raspberry Pi 4(以下、ラズパイ)にインストールするOSはRaspberry Pi OS 64bit(デスクトップ版)にしました。一度、何も考えずに32bitフルバージョンをインストールしたのですが、映像を扱う場合パフォーマンスを優先したいため64bit対応の方が望ましいと感じ再インストールしました。今どきは、Raspberry Pi Imagerを使って指定のOSイメージをmicroSDに書き込んでしまえば簡単に出来てしまいますね。というわけで詳細手順は省きます。

Raspberry Pi OS – Raspberry Pi

OSを入れ終わったらVNCとSSHでのアクセスを許可しておき、基本的にはMacからターミナルで接続して操作しました。

FFmpegのインストール

ラズパイからライブ配信をする場合、Windows/Macでも定番のフリーソフトOBSのLinux版が利用できます。
ダウンロード | OBS
・・・ですが、実際に試してみたところOBS自体の負荷が結構かかりそうなのでここでは紹介しないことにしました。

代わりに、動画変換ではド定番のFFmpegを利用します。
FFmpegの最新版を使いたい場合はソースからビルドする必要がありますが、とりあえずはaptで簡単にインストールしても十分だと思われます。

$ sudo apt-get install ffmpeg

FFmpegのバージョンを確認

$ ffmpeg -version
ffmpeg version 4.3.3-0+rpt2+deb11u1 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 10 (Debian 10.2.1-6)
configuration: --prefix=/usr --extra-version=0+rpt2+deb11u1 --toolchain=hardened --incdir=/usr/include/aarch64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-mmal --enable-neon --enable-v4l2-request --enable-libudev --enable-epoxy --enable-sand --libdir=/usr/lib/aarch64-linux-gnu --arch=arm64 --enable-pocketsphinx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
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
libavresample   4.  0.  0 /  4.  0.  0
libswscale      5.  7.100 /  5.  7.100
libswresample   3.  7.100 /  3.  7.100
libpostproc    55.  7.100 / 55.  7.100

4.3.3がインストールされました。

v4l2-ctlのインストール

今度はWEBカメラをUVC経由で確認したり、コントロールしたりするためにv4l2-ctlをインストールします。

$ sudo apt-get install v4l-utils

まずは接続中のUSBデバイス情報を確認します。

Logicool C270を接続して確認

$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
	/dev/video10
	/dev/video11
	/dev/video12
	/dev/video18
	/dev/media2

bcm2835-isp (platform:bcm2835-isp):
	/dev/video13
	/dev/video14
	/dev/video15
	/dev/video16
	/dev/video20
	/dev/video21
	/dev/video22
	/dev/video23
	/dev/media0
	/dev/media1

UVC Camera (046d:0825) (usb-0000:01:00.0-1.1):
	/dev/video0
	/dev/video1
	/dev/media3

余計な情報もありますが、UVCカメラとして認識されているC270と思われるものが/dev/video0,/dev/video1,/dev/media3と3種類でてきました。
デバイス名を指定してさらに詳細確認します。(–deviceを指定しなければ全件確認できますが長いので指定が無難)

$ v4l2-ctl --device /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x176
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 432x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 544x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 752x416
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x448
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 864x480
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x544
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x720
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1024x576
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1184x656
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x960
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
	[1]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x176
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 432x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 544x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 752x416
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 864x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x544
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1024x576
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1184x656
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x960
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)

動画規格としては、YUYV 4:2:2Motion-JPEG, compressed、の2種類に対応しており、それぞれ解像度とフレームレートの組み合わせが用意されていることがわかる。
YUYV 4:2:2の方がRAW(映像ソースそのまま)なのでフレームレートが少ないんですね。

ちなみに、

$ v4l2-ctl --device /dev/video1 --list-formats-ext
$ v4l2-ctl --device /dev/media3 --list-formats-ext

とやっても結果を得られなかったので/dev/video0が正しいデバイス名だと分かる。

ちなみに、上記出力だと長過ぎて見にくいので、ffmpegと組み合わせると下記のようなコーデックと解像度だけを見やすく表示もできる。

$ ffmpeg -f video4linux2 -list_formats all -i /dev/video0
(省略)
[video4linux2,v4l2 @ 0x557d3e8fa0] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
[video4linux2,v4l2 @ 0x557d3e8fa0] Compressed:       mjpeg :          Motion-JPEG : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960

Logicool C920を接続して確認

続いて上位機種にあたるC920を接続して確認します。
※旧モデルなので、現在はC920nとして販売されているものが近いスペックかと思います。

$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
	/dev/video10
	/dev/video11
	/dev/video12
	/dev/video18
	/dev/media2

bcm2835-isp (platform:bcm2835-isp):
	/dev/video13
	/dev/video14
	/dev/video15
	/dev/video16
	/dev/video20
	/dev/video21
	/dev/video22
	/dev/video23
	/dev/media0
	/dev/media1

HD Pro Webcam C920 (usb-0000:01:00.0-1.1):
	/dev/video0
	/dev/video1
	/dev/media3

今度はちゃんとHD Pro Webcam C920として機種名が認識されています。
デバイス名を指定してさらに詳細確認します。(–deviceを指定しなければ全件確認できますが長いので指定が無難)

$ v4l2-ctl --device /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x90
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 432x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 864x480
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x720
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1024x576
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1600x896
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1920x1080
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 2304x1296
			Interval: Discrete 0.500s (2.000 fps)
		Size: Discrete 2304x1536
			Interval: Discrete 0.500s (2.000 fps)
	[1]: 'H264' (H.264, compressed)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x90
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 432x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 864x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1024x576
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1600x896
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
	[2]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x90
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 432x240
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 864x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 960x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1024x576
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1600x896
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)

動画規格としては、YUYV 4:2:2H.264, compressedMotion-JPEG, compressed、の3種類に対応しており、それぞれ解像度とフレームレートの組み合わせが用意されていることがわかる。上位機種なのでh264エンコードに対応しているということですね。(後に重要なポイントとなります。)

$ ffmpeg -f video4linux2 -list_formats all -i /dev/video0
(省略)
[video4linux2,v4l2 @ 0x559ca32fa0] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 160x90 160x120 176x144 320x180 320x240 352x288 432x240 640x360 800x448 800x600 864x480 960x720 1024x576 1280x720 1600x896 1920x1080 2304x1296 2304x1536
[video4linux2,v4l2 @ 0x559ca32fa0] Compressed:        h264 :                H.264 : 640x480 160x90 160x120 176x144 320x180 320x240 352x288 432x240 640x360 800x448 800x600 864x480 960x720 1024x576 1280x720 1600x896 1920x1080
[video4linux2,v4l2 @ 0x559ca32fa0] Compressed:       mjpeg :          Motion-JPEG : 640x480 160x90 160x120 176x144 320x180 320x240 352x288 432x240 640x360 800x448 800x600 864x480 960x720 1024x576 1280x720 1600x896 1920x1080

alsa, libasoundのインストール

ついでに、音声入力(マイク)も確認します。
音声の操作にはalsaを使いますがこれは ffmpeg のインストールの時に依存で勝手に入っています。
不足している libasound をインストールします。

$ sudo apt-get install libasound2-dev

音声デバイスを確認してみましょう。

$ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 3: U0x46d0x825 [USB Device 0x46d:0x825], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

カード3、デバイス0、サブデバイス0なのでFFmpegから指定する場合 -i hw:3,0,0 と指定する。
※デバイス、サブデバイスは自動判別してくれるので -i hw:3 で十分と思われる。

FFmpegでWEBカメラをキャプチャ

それでは実際にffmpegコマンドを使ってWEBカメラの映像をキャプチャしてみましょう。

C270のYUYV 4:2:2ソースを保存

まずは、WEBカメラのRAWストリームをキャプチャし動画ファイルに保存します。保存する動画ファイルはh264のmp4ファイルにしてみましょう。

ffmpeg -y -hide_banner \
       -re -f alsa -thread_queue_size 16384 -ac 1 -channel_layout mono -ar 8000 -i hw:3,0,0 \
       -re -f v4l2 -thread_queue_size 16384 -input_format yuyv422 -video_size 1280x720 -framerate 5 -i /dev/video0  \
       -c:v libx264 -b:v 2M -vsync 1 -r 5 -g 10 -sc_threshold -1 -preset veryfast -s 1280x720 \
       -c:a aac -b:a 64k -ar 8000 \
       c270_yuyv422.mp4

-y 同じファイル名が合った場合は上書き
-hide_banner Configureなど多すぎる出力を制限
-f alsa 音声フォーマットにalsaを使う
-thread_queue_size 16384 バッファを指定
-ac 1 音声をモノラル(1)に指定(C270がモノラルだから)
-channel_layout mono 音声をモノラル(mono)に指定(C270がモノラルだから)
-ar 8000 音声サンプリングレートを8000Hzに指定。電話並の低品質(パフォーマンス優先のため)
-i hw:3,0,0 上述した音声デバイスの場所
-f v4l2 映像フォーマットをv4l2=video4linux2に指定(USBデバイスを使う)
-thread_queue_size 16384 バッファを指定
-input_format yuyv422 USBから取り出す映像コーデック
-video_size 1280x720 USBから取り出す映像サイズ
-framerate 5 USBから取り出す映像フレームレート
-i /dev/video0 映像デバイスの場所
-c:v libx264 映像コーデックを指定
-b:v 2M 映像ビットレートを指定
-vsync 1 映像同期設定。1で固定フレームレート
-r 5 フレームレートを指定
-g 10 GOPを指定
-sc_threshold -1 シーンチェンジ検出の閾値。-1は無効
-preset veryfast エンコードのスピードと圧縮率に影響するプリセット。veryfastがちょうど良さそう
-s 1280x720 映像の出力サイズ
-c:a aac 音声コーデック
-b:a 24k 音声ビットレート
-ar 8000 出力ファイルにも音声サンプリングレートを指定
c270_yuyv422.mp4 出力ファイル名

Input #0, alsa, from 'hw:3,0,0':
  Duration: N/A, start: 1643258247.558485, bitrate: 256 kb/s
    Stream #0:0: Audio: pcm_s16le, 16000 Hz, mono, s16, 256 kb/s
Input #1, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 427283.462984, bitrate: 73728 kb/s
    Stream #1:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 73728 kb/s, 5 fps, 5 tbr, 1000k tbn, 1000k tbc
Stream mapping:
  Stream #1:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
  Stream #0:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
[libx264 @ 0x55711cd650] using cpu capabilities: ARMv8 NEON
[libx264 @ 0x55711cd650] profile High 4:2:2, level 3.1, 4:2:2, 8-bit
[libx264 @ 0x55711cd650] 264 - core 160 r3011 cde9a93 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=10 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=abr mbtree=1 bitrate=2000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'c270_yuyv422.mp4':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv422p(progressive), 1280x720, q=-1--1, 2000 kb/s, 5 fps, 10240 tbn, 5 tbc
    Metadata:
      encoder         : Lavc58.91.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 0 vbv_delay: N/A
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 64 kb/s
    Metadata:
      encoder         : Lavc58.91.100 aac

映像ソースは非圧縮のyuyv422であるため、70Mbpsと結構重い印象。
とりあえず変換はできた。

変換中のCPU利用率は7〜8%

C270のMJPEGソースを保存

RAWソースは重すぎるので、次はMJPEGストリームをキャプチャし動画ファイルに保存します。保存する動画ファイルはh264のmp4ファイル。

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 1 -channel_layout mono -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format mjpeg -video_size 1280x720 -framerate 5 -i /dev/video0  \
       -c:v libx264 -b:v 2M -vsync 1 -r 5 -g 10 -sc_threshold -1 -preset veryfast -s 1280x720 \
       -c:a aac -b:a 64k -ar 48000 \
       c270_mjpeg.mp4

変更したオプションは、

-input_format mjpeg WEBカメラから取り出すフォーマットをMJPEGに変更
-ar 48000 音声サンプリングレートを入力ソースと同じ48000Hzに指定。8000とかだとエラーになったため

Input #0, alsa, from 'hw:3,0,0':
  Duration: N/A, start: 1643258564.375222, bitrate: 256 kb/s
    Stream #0:0: Audio: pcm_s16le, 16000 Hz, mono, s16, 256 kb/s
[mjpeg @ 0x5580884c30] unable to decode APP fields: Invalid data found when processing input
Input #1, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 427600.276723, bitrate: N/A
    Stream #1:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, 5 fps, 5 tbr, 1000k tbn, 1000k tbc
Stream mapping:
  Stream #1:0 -> #0:0 (mjpeg (native) -> h264 (libx264))
  Stream #0:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
[mjpeg @ 0x5580885070] unable to decode APP fields: Invalid data found when processing input
[libx264 @ 0x5580887800] using cpu capabilities: ARMv8 NEON
[libx264 @ 0x5580887800] profile High 4:2:2, level 3.1, 4:2:2, 8-bit
[libx264 @ 0x5580887800] 264 - core 160 r3011 cde9a93 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=10 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=abr mbtree=1 bitrate=2000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
[aac @ 0x558088f910] Too many bits 8192.000000 > 6144 per frame requested, clamping to max
Output #0, mp4, to 'c270_mjpeg.mp4':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuvj422p(pc, progressive), 1280x720, q=-1--1, 2000 kb/s, 5 fps, 10240 tbn, 5 tbc
    Metadata:
      encoder         : Lavc58.91.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 0 vbv_delay: N/A
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 8000 Hz, mono, fltp, 48 kb/s
    Metadata:
      encoder         : Lavc58.91.100 aac
[mjpeg @ 0x5580885070] unable to decode APP fields: Invalid data found when processing input
    Last message repeated 1 times

unable to decode APP fields: Invalid data found when processing inputというエラーが出続けるのは気になりましたがファイル自体は保存できました。

変換中のCPU利用率は7〜8%

C270のMJPEG 30fpsを保存

MJPEGは30fpsまで取り出せるので実験してみる

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 1 -channel_layout mono -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format mjpeg -video_size 1280x720 -framerate 30 -i /dev/video0  \
       -c:v libx264 -b:v 2M -vsync 1 -r 30 -g 60 -sc_threshold -1 -preset veryfast -s 1280x720 \
       -c:a aac -b:a 64k -ar 48000 \
       c270_mjpeg_30fps.mp4

-input_format mjpeg WEBカメラから取り出すフォーマットをMJPEGに変更
-framerate 30 WEBカメラから取り出すフレームレートを30まで上げる
-r 30 フレームレートを指定
-g 60 GOPを指定

Input #0, alsa, from 'hw:3,0,0':
  Duration: N/A, start: 1643267484.662625, bitrate: 768 kb/s
    Stream #0:0: Audio: pcm_s16le, 48000 Hz, mono, s16, 768 kb/s
[mjpeg @ 0x559ab55c30] unable to decode APP fields: Invalid data found when processing input
Input #1, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 436520.540001, bitrate: N/A
    Stream #1:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
Stream mapping:
  Stream #1:0 -> #0:0 (mjpeg (native) -> h264 (libx264))
  Stream #0:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
[mjpeg @ 0x559ab56070] unable to decode APP fields: Invalid data found when processing input
[libx264 @ 0x559ab58800] using cpu capabilities: ARMv8 NEON
[libx264 @ 0x559ab58800] profile High 4:2:2, level 3.1, 4:2:2, 8-bit
[libx264 @ 0x559ab58800] 264 - core 160 r3011 cde9a93 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=60 keyint_min=6 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=abr mbtree=1 bitrate=2000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'c270_mjpeg_30fps.mp4':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuvj422p(pc, progressive), 1280x720, q=-1--1, 2000 kb/s, 30 fps, 15360 tbn, 30 tbc
    Metadata:
      encoder         : Lavc58.91.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 0 vbv_delay: N/A
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 64 kb/s
    Metadata:
      encoder         : Lavc58.91.100 aac
[mjpeg @ 0x559ab56070] unable to decode APP fields: Invalid data found when processing input

やはりunable to decode APP fields: Invalid data found when processing inputというエラーが出ますが、30fpsで保存できたようです。

処理量が増えたためか、変換中のCPU利用率は23〜25%程度でした。

C920のYUYV 4:2:2ソースを保存

続いて、上位機種C920のRAWストリームをキャプチャし動画ファイルに保存します。保存する動画ファイルはh264のmp4ファイル 5fps。
※ここから、ffmpeg実行中のログ表示は省略します。

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 2 -channel_layout stereo -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format yuyv422 -video_size 1920x1080 -framerate 5 -i /dev/video0  \
       -c:v libx264 -b:v 3M -vsync 1 -r 5 -sc_threshold -1 -preset veryfast -s 1920x1080 \
       -c:a aac -b:a 64k -ar 48000 \
       c920_yuyv422.mp4

上位機種なので1080pに対応しているので1920×1080を取り出します。
また音声もステレオに対応しているので2チャンネル録音します。

-ac 2 音声をステレオ(2)に指定(C920がステレオだから)
-channel_layout stereo 音声をモノラル(stereo)に指定(C920がステレオだから)
-input_format yuyv422 USBから取り出す映像コーデック
-video_size 1920x1080 USBから取り出す映像サイズ
-s 1920x1080 映像の出力サイズ

映像ソースは非圧縮のyuyv422であるため、165Mbpsと結構重い印象。
とりあえず変換はできた。

変換中のCPU利用率は10%前後

C920のMJPEGソースを保存

続いて、上位機種C920のMJPEGストリームをキャプチャし動画ファイルに保存します。保存する動画ファイルはh264のmp4ファイル 30fps。

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 2 -channel_layout stereo -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format mjpeg -video_size 1920x1080 -framerate 30 -i /dev/video0  \
       -c:v libx264 -b:v 3M -vsync 1 -r 30 -sc_threshold -1 -preset veryfast -s 1920x1080 \
       -c:a aac -b:a 64k -ar 48000 \
       c920_mjpeg_30fps.mp4

-input_format mjpeg USBから取り出す映像コーデック
-framerate 30 WEBカメラから取り出すフレームレートを30まで上げる
-r 30 フレームレートを指定
-g 60 GOPを指定

CPU 37% 20fps speed=0.56x

MJPEGをFull HDで30fpsとなると流石に処理量が多いらしく、CPU高めでフレームも落としがちでした。

C920のH264ソースを保存

続いて、C920のH264ストリームをキャプチャし動画ファイルに保存します。圧縮率が高いので負荷が落ちることを期待しています。

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 2 -channel_layout stereo -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format h264 -video_size 1920x1080 -framerate 30 -i /dev/video0  \
       -c:v libx264 -b:v 3M -vsync 1 -r 30 -sc_threshold -1 -preset veryfast -s 1920x1080 \
       -c:a aac -b:a 64k -ar 48000 \
       c920_h264_30fps.mp4

-input_format h264 USBから取り出す映像コーデック

CPU 27% 23fps speed=0.7x

やはりH264の方が軽量らしくMJPEGの時よりもCPU負荷が引くく、フレームレートも23と少し改善。ただし、やはり30フレームは取得できないんだなと。

H264を無変換で保存できるか

さて最後に少し実験です。
C920がH264ストリームをキャプチャできるということで、変換無しでそのままmp4ファイルに保存できないか試します。

ffmpeg -y -hide_banner \
       -f alsa -thread_queue_size 16384 -ac 2 -channel_layout stereo -ar 48000 -i hw:3,0,0 \
       -f v4l2 -thread_queue_size 16384 -input_format h264 -video_size 1920x1080 -framerate 30 -i /dev/video0  \
       -c:v copy -r 30 -s 1920x1080 \
       -c:a aac -b:a 64k -ar 48000 \
       c920_h264_copy.mp4

-c:v copy 変換しない場合はcopyを指定する

CPU 1.5% 15fps speed=1.0x

映像が無変換だからかほとんどCPUを消費せずに保存ができました。
しかし、30fps指定ですが処理的には15fpsしか取り出せていないようにみえるので、USBの処理が追いついていない?などちょっと不思議な挙動でした。

また、

[mp4 @ 0x5591fb1390] Non-monotonous DTS in output stream 0:0; previous: 0, current: -2560; changing to 1. This may result in incorrect timestamps in the output file.
[mp4 @ 0x5591fb1390] Non-monotonous DTS in output stream 0:0; previous: 1, current: -2069; changing to 2. This may result in incorrect timestamps in the output file.
[mp4 @ 0x5591fb1390] Non-monotonous DTS in output stream 0:0; previous: 2, current: -1516; changing to 3. This may result in incorrect timestamps in the output file.
[mp4 @ 0x5591fb1390] Non-monotonous DTS in output stream 0:0; previous: 3, current: -1024; changing to 4. This may result in incorrect timestamps in the output file.
[mp4 @ 0x5591fb1390] Non-monotonous DTS in output stream 0:0; previous: 4, current: -533; changing to 5. This may result in incorrect timestamps in the output file.

というエラーが出てしまったので、気になっていたのですが一応保存された動画ファイルは再生できたので深入りはしないでいますが、これの解消方法などご存知の方がいればコメントいただけると助かります。

まとめ

というわけで、とりあえずWEBカメラからの映像を動画ファイルに保存するというところまではできそうです。

一方、1080p 30fpsくらいの画質ですでにCPUを結構使ってしまっているので最後に実験したh264無変換にするなり画質を落とすなりしないと長時間の安定稼働はできない気がしています。

さて、長くなってしまったので一旦記事はここまでにしますが次回はさらにCPU負荷の改善のためにハードウェアエンコードを使った変換を試してみたいと思います。

ロジクール Webカメラ C270n ブラック HD 720P ウェブカム ストリーミング 小型 シンプル設計 ウェブカメラ 国内正規品 2年間メーカー保証
B07QMKND9M

ロジクール Webカメラ C920n ブラック フルHD 1080P ウェブカム ストリーミング 自動フォーカス ステレオマイク ウェブカメラ 国内正規品 2年間メーカー保証 ブラック
B07QQR6G5N

-ffmpeg, RaspberryPi, ガジェット, 小技集

執筆者:


comment

メールアドレスが公開されることはありません。

関連記事

Ffmpegで複数動画を結合して一つの動画に出力

いつも、動画変換においてやりたいことがあってもコマンドを思い出せないFfmpeg。今回もこのごろ良く使うものを自分用のメモを兼ねて記録しておきます。

no image

MovableType:PostToTwitterプラグインを入れてみた

いいのを見付けたので早速インストールしました。 でうまくいくか試すのを踏まえエントリーします。 最近はやりのTwitterに、エントリーのタイトルとパーマリンクのTinyURLを投稿するプラグインを作 …

Googleドキュメントのフォーム機能からGoogle Apps Scriptを使ってメール送信

【2014/12/26:追記】 この記事はGoogleの仕様変更などで内容が古くなっていたため、最新の情報で書き換えました。 リンク先の記事を参照してください。 Googleドライブのフォーム機能から …

[N]ネタフル x [S]シカマケ = ブログデザイン勉強会 第4回:最終回でラフ案発表

昨日の4/23(木)、ついに最終回を迎えた「[N]ネタフル x [S]シカマケ = ブログデザイン勉強会」に参加してきました。 ▼前回まではこちら、 ・[N]ネタフル x [S]シカマケ = ブログデ …

no image

第16回:サムネイル作成APIをサーバサイドで簡単に切り替える方法

以前に、サムネイルAPIをJavaScriptで簡単に切り替える方法をエントリーしました。 サービスが使えなくなればサムネイルを外すなり他のサービスに切り替えるなりする作業が発生します。MT等のブログ …

スポンサードリンク

スポンサードリンク