WSL2でUSBカメラを使う – 後編

WSL2でUSBカメラを使う - 後編 WSL
スポンサーリンク

2025/02/28更新

2022年5月に作成した記事を、Windows 11 + Ubuntu 24.04 LTSの環境を念頭に更新しました。

前回はUSBIPD-WINというツールを使って、WSL2のLinuxからWindows上のUSBデバイスを認識できるようにしました。

しかしまだWSL2でUSBカメラは使えません。今回はこの問題を解決したいと思います。

USBIPD-WINを導入していない場合は前編をご確認ください。

404 NOT FOUND | メモ置場のブログ
試したことをとりあえずメモに!
スポンサーリンク

LinuxとUSBカメラ

LinuxでUSBカメラを利用する場合は、一般的にVideo for Linux 2(Video4Linux 2, V4L2)という仕組みを利用します。

Linux Kernel Media Documentation — The Linux Kernel documentation

V4L2では、さまざまなビデオカメラのドライバーをサポートしています。

最近のUSBカメラはUSB Video Class(UVC)に対応しているものが多く、V4L2とUVCドライバーという組み合わせでUSBカメラが利用できるケースが多いようです。

この「V4L2」と「UVCドライバー」はいずれもLinux Kernel内の機能であり、Linux Kernelがこれらの機能を有効にする設定で作られている(コンパイルされている)必要があります。

私が使っているWSL2のKernelでどうなっているか調べてみましょう。ちなみにLinuxカーネルのバージョンは次のようになっています。

$ uname -r
5.15.167.4-microsoft-standard-WSL2

まずV4L2の状況です。

$ zgrep CONFIG_VIDEO_V4L2 /proc/config.gz

何も表示されません。つまりV4L2は有効になっていないということです。

UVCの状況も確認してみます。

$ zgrep CONFIG_USB_VIDEO_CLASS /proc/config.gz

こちらも何も表示されません。

したがって、WSL2で提供されているこのLinux KernelではUSBカメラが利用できないことがわかります。

スポンサーリンク

WSL2のLinux Kernelのコンパイル

WSL2のLinux KernelでV4L2とUVCを利用できるようにするためには、Linux Kernelの再コンパイルが必要です。

この作業はWSL2のLinux上で行います。今回はWSL2のLinuxとしてUbuntu 24.04 LTSを使った例を紹介します。

コンパイルのためのツールを入手

Linux Kernelをコンパイルするためにはさまざまなツールが必要です。

Ubuntuでは下記コマンドで必要なツール一式を導入できます。

sudo apt-get update
sudo apt-get install build-essential flex bison dwarves libssl-dev libelf-dev git libncurses-dev

これでツールの入手は完了です。

ソースの取得

次にLinux Kernelのソースコードを取得します。

WSL2のLinux Kernelのソースは下記で公開されています。

GitHub - microsoft/WSL2-Linux-Kernel: The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2)
The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2) - microsoft/WSL2-Linux-Kernel

公式にリリースされたカーネルバージョンは下記のページにリストアップされています。

Releases · microsoft/WSL2-Linux-Kernel
The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2) - microsoft/WSL2-Linux-Kernel

このページで自分が使っているカーネルバージョンと同じものを探します。そして「Assets」を開いて「Source code (tar.gz)」をダウンロードしましょう。

リリースされたカーネルのソース

「Source code (tar.gz)」を右クリックしてリンクアドレスをコピーして、wgetコマンドでファイルをダウンロードすると楽だと思います。

mkdir -p wsl-kernel
cd wsl-kernel
wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.15.167.4.tar.gz

ダウンロードが完了したらファイルを展開しておきます。

tar xfvz linux-msft-wsl-5.15.167.4.tar.gz

これで「WSL2-Linux-Kernel-linux-msft-wsl-5.15.167.4」というディレクトリの中にカーネルソースが展開されます。

設定(コンフィグレーション)

続いてLinux Kernelの設定(コンフィグレーション)をします。

これをゼロからやるのは大変なので、現状の設定をベースに行うのがオススメです。現状の設定はソースコードのMicrosoft/config-wslに記載されているのでこれを利用します。

/proc/config.gzを展開したものを利用しても構いません。

cd WSL2-Linux-Kernel-linux-msft-wsl-5.15.167.4/
make menuconfig KCONFIG_CONFIG=Microsoft/config-wsl

これで次のようなLinux Kernelの設定画面が表示されます

Linux Kernelの設定画面

この設定画面ではカーソルスペースエンターTabを駆使して操作します。

まずはカーネルのバージョン名をオフィシャルなものから変更しておきます。

  • 「General setup」→「Local version」にある「-microsoft-standard-WSL2」を「-microsoft-standard-WSL2-uvc」変更

「General setup」の画面の3番目が「Local version」です。ここでエンターを押すとバージョン名を入力できるようになるので、「-microsoft-standard-WSL2」を「-microsoft-standard-WSL2-uvc」に変更します。

Local versionの変更

次にV4L2を有効にしましょう。

  • 「Device Drivers」→「Multimedia support」→「Filter media drivers」と「Autoselect ancillary drivers」を有効化
  • 「Device Drivers」→「Multimedia support」→「Media device types」→「Cameras and video grabbers」を有効化
  • 「Device Drivers」→「Multimedia support」→「Video4Linux options」→「V4L2 sub-device userspace API」を有効化

有効化する際は、モジュール(<M>)でもビルトイン(<*>)でもどちらでも大丈夫です。

さらにUVCを有効にしましょう。

  • 「Device Drivers」→「Multimedia support」→「Media drivers」→「Media USB Adapters」→「USB Video Class (UVC)」と「UVC input events device support」を有効化

ここでもモジュールでもビルトインでもどちらでも大丈夫です。

UVC以外のUSBカメラを使いたい場合は「Media USB Adapters」で表示されるドライバーを有効化しておくと使えるかもしれません。

とくに「GSPA based webcams」では多くのWebカメラに対応しているようです。

gspca devices - LinuxTVWiki

以上の設定が終わったらTabで<Exit>を選び続け、一番上の階層で<Exit>を選ぶと「Do you wish to save your new configuration?」と聞かれるので<Yes>を選択して保存しましょう。

なお設定は「Microsoft/config-wsl」に上書き保存されます。

ビルド

先ほど保存した設定を使ってビルドします。

make -j $(nproc) KCONFIG_CONFIG=Microsoft/config-wsl

ビルドは結構時間がかかります。最終的に次のように「Kernel: arch/x86/boot/bzImage is ready」となればビルド成功です

ビルドの完了

この最後の行に表示されたbzImageがビルドして生成されたLinux Kernelになります。

このファイルはWindows側にコピーする必要があります。

今回はWindowsのユーザディレクトリ(%UserProfile%)にwslというフォルダーをつくってそこにコピーしておきます。

mkdir -p /mnt/c/Users/Windowsでのユーザ名/wsl
cp arch/x86/boot/bzImage /mnt/c/Users/Windowsでのユーザ名/wsl/bzImage-uvc

今回は作成したLinux KernelをbzImage-uvcというファイル名でコピーしました。

カーネルモジュールのインストール

カーネルのビルドといっしょにカーネルモジュールも生成されているので、これが使えるようにインストールしておきます。

インストールにはsudoを使う必要がある点に注意してください。

sudo make modules_install KCONFIG_CONFIG=Microsoft/config-wsl

これで/lib/modules/5.15.167.4-microsoft-standard-WSL2-uvc以下にカーネルモジュールがコピーされます。

作成したLinux Kernelでの起動

自分で作成したLinux KernelをWSL2で使用するためには、「.wslconfig」というファイルをWindowsのユーザフォルダー(%UserProfile%)に作成する必要があります。

このフォルダーは「Windowsアイコンを右クリック」→「ファイル名を指定して実行」→「. (ピリオドを入力してOK)」で開くことができます。

ユーザフォルダーを開いたら「テキストドキュメント」を新規作成し、ファイル名を「.wslconfig」に変更します。

そしてこの「.wslconfig」の中身を次のようにします。

[wsl2]
kernel=C:\\Users\\Windowsのユーザ名\\wsl\\bzImage-uvc

つまりkernelというキーに先ほどコピーしたbzImageファイルを指定します。ただし、ファイルパスの「\」は「\\」とする必要があります。

「.wslconfig」ファイルを作成したら、PowerShell(あるいはWindowsターミナルで)次のコマンドを入力し、いったんWSL2を停止させます。

wsl --shutdown

そしてWSL2を再度開始します。

WSL2が起動したらLinux Kernelのリリース番号を表示させてみましょう。

$ uname -r
5.15.167.4-microsoft-standard-WSL2-uvc

このように、リリース番号(5.15.167.4)にカーネルのコンフィグレーションの「Local Version」で指定した文字列がついていればOKです。

またV4L2とUVCが有効になっていることも確認しておきましょう。

$ zgrep V4L2 /proc/config.gz
CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L2_I2C=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEOBUF2_V4L2=m
$ zgrep USB_VIDEO /proc/config.gz
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y

USBカメラの利用

V4L2とUVCに対応したLinux KernelでWSL2が動いていることを確認したら、USBカメラを試してみましょう。

今回は下記のUSBカメラを利用しています。

USBカメラの接続

まず前回紹介した手順でUSBカメラをアタッチします。

WSL2でUSBカメラを使う - 前編
今回はWSL2のUbuntuでUSBデバイスを認識できるようにしてみます。WSL2は仮想マシンのようなものなので物理的なUSBポートは有りませんが、USBIPD-WINというツールを使うことでWindowsに接続されたUSBデバイスを認識できます。ただWSL2のLinux kernelにはUSBカメラのドライバーが含まれていないため、USBカメラを使うにはもう一工夫必要です。

Windows側でUSBカメラをアタッチすると、WSL2からはUSBカメラが接続された様に見えます。

そこでWSL2側でdmesgを実行してみます。次のように「Found UVC」という行があればUVCのカメラとして認識されています。

UVCを認識

また、ドライバー類をモジュールとしてビルドした場合はこのタイミングで自動的にロードされます。

$ lsmod
Module                  Size  Used by
uvcvideo              118784  0
videobuf2_vmalloc      16384  1 uvcvideo
videobuf2_memops       16384  1 videobuf2_vmalloc
videobuf2_v4l2         28672  1 uvcvideo
videobuf2_common       61440  4 videobuf2_vmalloc,videobuf2_v4l2,uvcvideo,videobuf2_memops
videodev              225280  3 videobuf2_v4l2,uvcvideo,videobuf2_common
mc                     49152  4 videodev,videobuf2_v4l2,uvcvideo,videobuf2_common

パーミッションの確認

USBカメラが無事に認識されると/dev以下にvideoで始めるファイル(デバイスノード)が作成されます。

$ ls -l /dev/video*
crw-rw---- 1 root video 81, 0  2月 28 00:49 /dev/video0
crw-rw---- 1 root video 81, 1  2月 28 00:49 /dev/video1

このパーミッションを見るとvideoグループに所属しているユーザがUSBカメラを利用できることになります。

自分がどのグループに属しているかは「groupsコマンド」で確認できます。

$ groups
ユーザ名 adm dialout cdrom floppy sudo audio dip video plugdev users netdev

このようにgroupsコマンドの実行結果にvideoが含まれていればOKです。

videoが含まれていない場合は、下記のコマンドでvideoグループに自分を追加しましょう。

sudo usermod -aG video $USER

なお、グループ追加後はターミナルを起動し直す(ログインし直す)方が良いと思います。

v4l-ctlでの確認

次にV4L2で今回接続したカメラが認識できるか確認してみます。この確認にはv4l2-ctlというツールを使いますのでv4l-utilsパッケージをインストールします。

sudo apt-get install v4l-utils

そしてv4l2-ctlでデバイスの情報を表示させてみます。

$ v4l2-ctl --all
Driver Info:
        Driver name      : uvcvideo
        Card type        : Microsoft® LifeCam HD-3000: Mi
        Bus info         : usb-vhci_hcd.0-1
        Driver version   : 5.15.167
        Capabilities     : 0x84a00001
                Video Capture
                Metadata Capture
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04200001
                Video Capture
                Streaming
                Extended Pix Format
Media Driver Info:
        Driver name      : uvcvideo
        Model            : Microsoft® LifeCam HD-3000: Mi
        Serial           :
        Bus info         : usb-vhci_hcd.0-1
        Media version    : 5.15.167
        Hardware revision: 0x00000106 (262)
        Driver version   : 5.15.167
Interface Info:
        ID               : 0x03000002
        Type             : V4L Video
Entity Info:
        ID               : 0x00000001 (1)
        Name             : Microsoft® LifeCam HD-3000: Mi                                                                       Function         : V4L2 I/O
        Flags            : default
        Pad 0x01000007   : 0: Sink
          Link 0x02000013: from remote pad 0x100000a of entity 'Extension 5' (Video Pixel Formatter): Data, Enabled, Immutable
Priority: 2
Video input : 0 (Input 1: ok)
Format Video Capture:
        Width/Height      : 640/480
        Pixel Format      : 'YUYV' (YUYV 4:2:2)
        Field             : None
        Bytes per Line    : 1280
        Size Image        : 614400
        Colorspace        : sRGB
        Transfer Function : Rec. 709
        YCbCr/HSV Encoding: ITU-R 601
        Quantization      : Default (maps to Limited Range)
        Flags             :
Crop Capability Video Capture:
        Bounds      : Left 0, Top 0, Width 640, Height 480
        Default     : Left 0, Top 0, Width 640, Height 480
        Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 640, Height 480, Flags:
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 640, Height 480, Flags:
Streaming Parameters Video Capture:
        Capabilities     : timeperframe
        Frames per second: 30.000 (30/1)
        Read buffers     : 0

User Controls

                     brightness 0x00980900 (int)    : min=30 max=255 step=1 default=133 value=133
                       contrast 0x00980901 (int)    : min=0 max=10 step=1 default=5 value=5
                     saturation 0x00980902 (int)    : min=0 max=200 step=1 default=83 value=83
        white_balance_automatic 0x0098090c (bool)   : default=1 value=1
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=2 value=2 (60 Hz)
                                0: Disabled
                                1: 50 Hz
                                2: 60 Hz
      white_balance_temperature 0x0098091a (int)    : min=2800 max=10000 step=1 default=4500 value=4500 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=50 step=1 default=25 value=25
         backlight_compensation 0x0098091c (int)    : min=0 max=10 step=1 default=0 value=0

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=1 value=3 (Aperture Priority Mode)
                                1: Manual Mode
                                3: Aperture Priority Mode
         exposure_time_absolute 0x009a0902 (int)    : min=5 max=20000 step=1 default=156 value=156 flags=inactive
                   pan_absolute 0x009a0908 (int)    : min=-201600 max=201600 step=3600 default=0 value=0
                  tilt_absolute 0x009a0909 (int)    : min=-201600 max=201600 step=3600 default=0 value=0
                  zoom_absolute 0x009a090d (int)    : min=0 max=10 step=1 default=0 value=0

V4L2も問題なく動作しているようです。

USBカメラの映像の表示

ここまできたらUSBカメラの映像を表示してみましょう。

今回はUVCに対応したツールである「guvcview」を使って見ます。インストールは下記のコマンドです。

sudo apt-get install guvcview libglx-mesa0

これでguvcviewというコマンドがつかるようになるので実行してみましょう。

guvcview --render=sdl

WSLgが使える環境であればこれで「Guvcview」という制御するウィンドウとカメラの映像を表示するウィンドウの2つのウィンドウが表示されます。

しかし、私の場合はカメラ映像を表示するウィンドウは真っ暗で何も表示されません。

カメラの映像が表示されない

guvcviewを起動したターミナルを確認すると

V4L2_CORE: Could not grab image (select timeout): リソースが一時的に利用できません

というメッセージが繰り返して表示されています。

このような場合はguvcviewの制御ウィンドウで解像度を下げてみましょう。

guvcviewの設定画面 - 解像度を320x240にする

私の環境では解像度を320×240まで下げると、カメラ映像が表示されるようになりました。

表示されたカメラの映像

WSL2でUSBデバイスを使う際に、USBをネットワーク(IP)に変換する処理が入っており、高い解像度ではデータ転送が間に合わないようです。

なお、フレームレートを下げると、VGA(640×480)ぐらいならなんとか表示させることができました。

VGAでのカメラ画像

ただ、映像にノイズが入ってしまっており、この設定での実用性には少々難があると感じます。

VGAでのカメラ画像

さらにフレームレートを下げるとノイズも消えますので、解像度を上げるにはフレームレートを下げるしかないようです。

この辺は現状の仕組みの限界なのかもしれません。

まとめ

今回はWSL2でUSBカメラを使えるようにしてみました。

WSL2のLinux KernelはV4L2やUVCが有効になっていないため、USBカメラを利用するにはLinux Kernelを自分でコンパイルして差し替える必要があります。

Linux Kernelを変更すればUSBIPD-WINと組み合わせることによってWSL2でUSBカメラを利用できます。ただ転送速度に難があるようなのが残念です。

次回はroot権限がなくてもUSBカメラを使えるようにしてみたいと思います。

2025/02/28追記

WSL2でsystemdが使えるようになったことにより、videoグループに属していれば、root権限がなくてもUSBカメラは使用できるようになりました。

したがって次回の記事は気にする必要はありません。

コメント

タイトルとURLをコピーしました