CM5でUSB接続のWEBカメラをコマンドで撮影する方法まとめ

Raspberry Piとカメラモジュールは、本体基板にあるCSI接続で直接繋げます。専用のコマンドアプリも用意されており、rpicam-stillコマンドで撮影ができます。
但し、これはCSIに接続するカメラモジュールで利用できるだけで、一般的なUSB接続のWEBカメラだと使えません。

rpicam-stillコマンド:
○ CSI接続のカメラモジュール
× 一般的なUSB接続のWEBカメラ

では、USBで接続するWEBカメラはどう撮影すれば良いのでしょうか。
他のソフトウェアで代用します。

GUIで撮影できるソフトウェアもありますが、プログラムやスクリプトに組み込めるようにコマンド(CUI)で操作する方法をご紹介します。
静止画と動画で別々のソフトウェアを使いました。

使用したRaspberry PiはComputeModule 5です。WEBカメラはロジクール製C270nです。

C720nはリリースは古い製品ですが、記事執筆時点でも販売されています。HD画質720P(1280×720)まで対応していて、マイクも内蔵されているタイプです。テレビ会議にはちょうど良い画質と音質です。お値段もお手頃ですから、Raspberry Piにはちょうど良い製品でした。

では、静止画の撮影、動画の録画を順番にご紹介します。

fswebcamで静止画を撮る

WEBカメラで撮影する静止画は、Raspberry Pi公式でも紹介されているソフトウェアfswebcamを使います。
aptでインストールできるのでお手軽です。

sudo apt install fswebcam

ユーザー(ここではraspida)をvideoグループに加えます。今ログインしているユーザー名などに置き換えて読んでください。
videoグループにログインしているユーザーを追加すれば、権限エラーがなく実行できます。

sudo usermod -a -G video raspida

撮影にあたり、基本の書式は次の通りシンプルです。

fswebcam test.jpg

但し、何もオプションを指定しないデフォルト(標準)だと、小さい解像度(352×288)になっていますね。

実際の解像度(352×288)

下部に薄いバーが表示され、右下に日時がみえますね。文字化けしている場合は、noto-fontsをインストールすると解消します。

文字化けしているならフォントも追加インストール:

sudo apt install fonts-noto-cjk

オプションはたくさんありますが、先ずは解像度を変えてみます。詳細はfswebcam --helpで確認してください。

-rオプションを付けると、解像度を指定できる。

fswebcam -r 1280x720 test.jpg

次に、--no-bannerオプションです。

画像の下部に日付と一緒に出ているバー状の出力をやめるオプションになります。
この2つのオプションで、ごく一般的な画像を撮影できました。

fswebcam -r 1280x720 --no-banner ファイル名.jpg

解像度1280×720でバナーなし

ファイル名に日付を入れる

fswebcamには日付けや連番といったファイル名の命名機能がありません。公式ではシェルスクリプトで代用するよう紹介されています。

シェルスクリプトを実行することで、日付けファイル名で撮影できるようになります。
記述する内容は3行です。次のように適当な場所にshファイルを新規に作り、実行権限を与えておきます。

nano webcam.sh
chmod +x webcam.sh

shの中身は、fswebcamコマンドを使い、1280×720で撮影させ、保存するファイル名を日付けにする内容です。

#!/bin/bash

DATE=$(date +"%Y-%m-%d_%H-%M-%S")
fswebcam -r 1280x720 --no-banner $DATE.jpg

作成したshファイルと同じディレクトリに移動しているなら、次のシェルコマンドで静止画の撮影を実行できます。

./webcam.sh

これで撮影する度に日付名の画像ファイルが保存されていきます。

ffmpegで動画を撮る

次は動画です。
こちらはffmpegを使うことで代用できます。
Raspberry Pi OSには最初からインストールされています。(version 8:5.1.6-0+deb12u1+rpt3)

Raspberry Piに繋いだWEBカメラ(USB)で動画を録画する際、ffmpegに様々なオプションを付けて実行することになります。
オプションについてはラズパイに関係なくffmpegや動画形式の話です。詳しくはffmpeg関連を別に調べてください。

今回はC270nを使い、先ずは次のコマンドオプションで試しました。

マイクも付いているカメラなので一緒に音声も録音しています。
最後に出力ファイル名をoutput.mkvとして指定しました。名前は任意で変更してください。

ターミナルでQを押下すれば録画を停止します。

ffmpeg -f alsa -i pulse -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -c:a aac output.mkv

入力ソースを音声が-f alsa -i pulseとし、動画は-f v4l2 -i /dev/video0で指定しています。
動画フォーマットを-input_format mjpegでmjpeg形式に指定、デバイス番号は/dev/video0で、-c:v copyは入力ソースから映像をそのままコピー(再エンコードなし)、-c:a aacが音声をAAC形式に変換、最後に作成する動画ファイル名にしています。

オプションの配置は順番があります。
基本は入力オプション-iの前に配置するか後に配置するかがあります。エラーやオプションが効いていないなら、挿入位置を再確認してください。

これが基本として、フレームレートを指定し、画面解像度を指定してみます。

ffmpeg -f alsa -i pulse -f v4l2 -input_format mjpeg -framerate 30 -video_size 800x600 -i /dev/video0 -c:v copy -c:a aac output_800x600.mkv

フレームレートは-framerate 30で30fps、画面解像度を-video_size 800x600-input_format mjpegの後に挿入しただけです。

H.264形式mp4

今度はmjpegではなく、生のyuyv422を入力ソースにしてから、h264へ変換させてH264のmp4を作成してみます。
これだとファイルサイズが抑えられます。

ffmpeg -f alsa -i pulse -f v4l2 -input_format yuyv422 -framerate 30 -video_size 800x600 -i /dev/video0 -c:v libx264 -vf format=yuv422p -c:a aac output.mp4

ターミナルの出力でも、H264でエンコード、AAC 48kHz、128kbpsと分かります。

Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(tv, progressive), 800x600, q=2-31, 20 fps, 10240 tbn
    Metadata:
      encoder         : Lavc59.37.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
  Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s

最終的なコマンド例

ffmpegのコマンド自体はオプションが豊富にあります。画質を変更したり、ファイルサイズを考慮したり、オプションの指定で変わります。
Raspberry Pi とは直接に関係がないため、ここでは使用したオプションしか紹介していませんが、気になるオプションはffmpegで調べてください。

WEBカメラで動画を録画するのに、Raspberry Pi に繋げたWEBカメラでは最終的に以下のようにしました。

H264でエンコードし、音声は高品質圧縮のOpusを使いました。オプションは一部省略形を用いています。

ffmpeg -f alsa -i pulse -f v4l2 -input_format yuyv422 -r 30 -s 600x360 -i /dev/video0 -c:v libx264 -vf format=yuv422p -c:a libopus -b:a 128k output.mp4

画面サイズはやや小さいものの、この設定だと30秒の動画が約1.8MBに収まりました。

生の動画ソースをH.264へ、生の音声をOpus形式の128kbpsに圧縮変換(エンコード)しています。

  Stream #1:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
  Stream #0:0 -> #0:1 (pcm_s16le (native) -> opus (libopus))

ffmpegのコマンド内で使用する入力ソースの場所など、異なるWEBカメラに置き換えるとどうなのかよく分からないと思います。
そのためにも、WEBカメラの情報を把握しておくと良いでしょう。
デバイスを指定する方法や対応フォーマットを知るためにも、WEBカメラをUSBケーブルで繋げた後、いくつかのコマンドを実行して調べておくのをオススメします。

以下、ffmpegコマンドで指定するWEBカメラの部分を調べる手順です。

WEBカメラのデバイス情報を調べる

WEBカメラを接続した後、lsusbコマンドで情報をみてみます。
これはUSB接続したデバイスなら共通の方法です。

lsusb

こんな感じで、3行目にあるWebcam C270のIDが046d:0825であることが分かりました。

Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 003 Device 002: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 1c4f:0027 SiGma Micro USB Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

ベンダーID:プロダクトIDで表されています。
他の製品でもロジクール(Logitech, Inc.)なら046dです。

デバイス番号を調べる

Linuxの場合、カメラデバイスを接続した時に割り当てられるデバイス番号(/dev/video*)を調べておきます。
一般的には1つしか繋げていないWEBカメラであればvideo0だと思います。

sudo udevadm info --query=all /dev/video1 | grep 'VENDOR_ID\|MODEL_ID\|SERIAL_SHORT'

実行後に出力された情報:

E: ID_MODEL_ID=0825
E: ID_SERIAL_SHORT=1811AF40
E: ID_VENDOR_ID=046d
E: ID_USB_MODEL_ID=0825
E: ID_USB_SERIAL_SHORT=1811AF40
E: ID_USB_VENDOR_ID=046d

先程調べたベンダーIDやモデルIDが同じことが分かります。これでvideo0がC720nだと確信が持てました。
もしも、ここがVIDEO1なら、ffmpegコマンドも同様に変更しないとなりません。

Raspberry Piに複数のカメラを繋いで居る場合、次のコマンドを使ってベンダーIDやUSBという表記から判別しておきます。

v4l2-ctl --list-devices
UVC Camera (046d:0825) (usb-1000480000.usb-1.4.2):
    /dev/video0
    /dev/video1
    /dev/media3

では、/dev/video0にUSBケーブルで接続しているWEBカメラが前提として進めます。

カメラが対応する解像度を調べる

先程のv4l2-ctlコマンドの別オプションで調べてみます。

v4l2-ctl --list-formats
v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YUYV' (YUYV 4:2:2)
    [1]: 'MJPG' (Motion-JPEG, compressed)

更にextを付けたコマンドだと詳細が表示されます。

v4l2-ctl --list-formats-ext
'YUYV' (YUYV 4:2:2)
Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)

'MJPG' (Motion-JPEG, compressed)
Size: Discrete 1280x720
            Interval: Discrete 0.033s (30.000 fps)

このように、C270はフレームレートを30にしたい場合、’YUYV’ (YUYV 4:2:2)形式だと640×360以下までしか対応していないことが分かりました。ちょっと小さいですよね。
‘MJPG’ (Motion-JPEG, compressed)形式なら1270xでも対応しています。

もう1つ。WEBカメラがキャプチャーしているフォーマットを調べておきます。

v4l2-ctl --get-fmt-video
Format Video Capture:
    Width/Height      : 640/360
    Pixel Format      : 'YUYV' (YUYV 4:2:2)
    Field             : None
    Bytes per Line    : 1280
    Size Image        : 460800
    Colorspace        : sRGB
    Transfer Function : Rec. 709
    YCbCr/HSV Encoding: ITU-R 601
    Quantization      : Default (maps to Limited Range)
    Flags             : 

フォーマット設定を変更することもできます。
コマンドで変更して録画すると、この内容も変わっているハズです。

v4l2-ctlコマンドはオプションなどがたくさんあるため、v4l2-ctl --helpで確認してください。

今回と同じC720nのWEBカメラであれば、CM5でもPi 5でも、ここに記載したコマンドで問題無く撮影が可能です。
異なるWEBカメラの場合は性能が異なりますから、カメラが対応している形式を調べてからコマンドで指定してください。

一般的なUSB接続するWEBカメラをRaspberry Pi で撮影する方法をご紹介しました。

静止画をfswebcam、動画をffmpegで撮影・録画しました。
コマンドでの撮影なら、プログラムやスクリプトで使用できます。CSI接続する公式のカメラモジュールだけではなく、WEBカメラも同じように動作させられました。

公式のカメラモジュールなら、Raspberry Piからもっと制御することが可能です。
専用コマンドアプリも用意されていますし、マニュアルも公式サイトにあります。

とはいえ、手軽に汎用のWEBカメラを使いたい場合、今回の内容を参考にしてください。

Mediainfoで調べる

mediainfoというパッケージアプリを知りました。コマンドラインツールとGUI版があり、手軽にメディア情報を取得できて便利でした。
撮影した動画ファイルの情報なので、撮影する前は意味がありませんが、オプションをイジって保存した動画を見比べるのに重宝です。
つい、オプションの指定が何だったか忘れてしまうので、より良い画質やファイルサイズとのバランスなど、オプションを変更する試行錯誤に役立ちました。

sudo apt install mediainfo mediainfo-gui

コマンドならmediainfoコマンド+ファイル名で出力できます。
動画で撮影したファイルを指定してみました。フォーマット情報など詳しく分かります。

mediainfo output.mp4

GUI版も一緒にインストールしました。メニューに登録されていて、動画ファイルを選ぶだけで使えます。

マルチプラットフォームのパッケージなので、Raspberry Pi OS以外のWindows、macOS、各種Linuxで動作します。

GUIでWEBカメラ

最後に、もしもRaspberry Pi のデスクトップ画面でUSB接続のWEBカメラを使いたいなら、Raspberry Piと相性が良いGuvcviewがオススメです。
aptパッケージなので導入も簡単です。

sudo apt install guvcview

何も設定しなくても、USBケーブルを接続した後、Guvcviewを起動したら既にキャプチャーされています。
Raspberry Pi OSのデスクトップで使うなら一度試してみてください。


記事寄稿:ラズパイダ

非エンジニアでも楽しく扱えるRaspberry Pi 情報サイト raspida.com を運営。ラズベリーパイに長年触れた経験をもとに、ラズベリーパイを知る人にも、これから始めたいと興味を持つ人にも参考になる情報・トピックを数多く発信。PiLinkのサイトへは産業用ラズベリーパイについて技術ブログ記事を寄稿。