2025/02/28更新
2022年5月に作成した記事を、Windows 11 + Ubuntu 24.04 LTSの環境を念頭に更新しました。
前回はUSBIPD-WINというツールを使って、WSL2のLinuxからWindows上のUSBデバイスを認識できるようにしました。
しかしまだWSL2でUSBカメラは使えません。今回はこの問題を解決したいと思います。
USBIPD-WINを導入していない場合は前編をご確認ください。

LinuxとUSBカメラ
LinuxでUSBカメラを利用する場合は、一般的にVideo for Linux 2(Video4Linux 2, V4L2)という仕組みを利用します。
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のソースは下記で公開されています。
公式にリリースされたカーネルバージョンは下記のページにリストアップされています。
このページで自分が使っているカーネルバージョンと同じものを探します。そして「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の設定画面が表示されます
この設定画面ではカーソル・スペース・エンター・Tabを駆使して操作します。
まずはカーネルのバージョン名をオフィシャルなものから変更しておきます。
- 「General setup」→「Local version」にある「-microsoft-standard-WSL2」を「-microsoft-standard-WSL2-uvc」変更
「General setup」の画面の3番目が「Local version」です。ここでエンターを押すとバージョン名を入力できるようになるので、「-microsoft-standard-WSL2」を「-microsoft-standard-WSL2-uvc」に変更します。
次に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カメラに対応しているようです。
以上の設定が終わったら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カメラをアタッチします。

Windows側でUSBカメラをアタッチすると、WSL2からはUSBカメラが接続された様に見えます。
そこでWSL2側でdmesgを実行してみます。次のように「Found 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の制御ウィンドウで解像度を下げてみましょう。
私の環境では解像度を320×240まで下げると、カメラ映像が表示されるようになりました。
WSL2でUSBデバイスを使う際に、USBをネットワーク(IP)に変換する処理が入っており、高い解像度ではデータ転送が間に合わないようです。
なお、フレームレートを下げると、VGA(640×480)ぐらいならなんとか表示させることができました。
ただ、映像にノイズが入ってしまっており、この設定での実用性には少々難があると感じます。
さらにフレームレートを下げるとノイズも消えますので、解像度を上げるにはフレームレートを下げるしかないようです。
この辺は現状の仕組みの限界なのかもしれません。
まとめ
今回は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カメラは使用できるようになりました。
したがって次回の記事は気にする必要はありません。
コメント