Windows環境でDockerコンテナにUSBウェブカメラを認識させてみる
2018.08.28
こんにちは。
ユニトラストでエンジニアをしている我妻です。
昨年頃から機械学習についての話題を耳にすることも増えましたが、試しに触ろうと思っても出てくる情報はMacやLinuxでの情報が多く、
Windows環境での情報はまだあまり多くありません。
そこで、業務内容や宗教的理由などにより利用できる開発環境がWindowsマシンのみであるという人であっても、
Dockerを使えば比較的簡単に開発環境を構築できるのではないかと思い、試してみたことをまとめてみました。
以下、本記事執筆時点での動作環境です。
OS: Windows 10 Pro (build 17134.48) Docker for Windows: 18.03.1-ce-win65 Vagrant: 2.1.1 Vagrant Box: bento/ubuntu-16.04 VirtualBox: 5.2.12 Docker: 18.03.1-ce
Docker for Windowsを利用する
一番簡単な方法のように思えますが、結論から言うと現状こちらの方法は無理なようです。
Docker for Windows公式リポジトリのIssueを参照する限り、現在の仕様としてHyper-V上で動いているLinuxコンテナにUSBデバイスを認識させることができないようです。(2018/06/30時点で明確な回答なし)
Vagrantを利用する
Docker for Windowsが使えない以上、従来からあるVagrant経由でVirtualBoxを立ち上げてその仮想マシン上でDockerコンテナを起動するという方法を試してみます。
VirtualBox上の仮想マシンにUSBウェブカメラを認識させる
まずはVagrantで立ち上げたVMにWindowsマシンに接続したUSBウェブカメラを認識させます。
手動で認識させる場合は、Vagrantイメージの起動後にVirtualBoxのターミナルからデバイス>Webカメラ>”デバイス名”と選択する。
1.VM起動時

2.VirtualBoxコンソールからWebカメラをマウント

3.USBデバイスが追加された

またはホスト上でVBoxManageからVM上にマウントさせる必要があります。
その場合は以下のようにWihdows上でコマンドプロンプトにて実行していきます。
# vboxmanage.exeへのpathは設定済み
# Windowsホスト上で認識しているUSBウェブカメラをリスト表示
$ vboxmanage list webcams Video Input Devices: 1
Video Input Devices: 1
.1 "Logicool HD Webcam C615"
\\?\usb#vid_046d&pid_082c&mi_02#6&84bb6b4&0&0002#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
# {}内がVMのUUID
$ vboxmanage list runningvms # 起動中のVMを一覧表示する
"usbdev_sample_default_1527315320986_28174" {35cd756a-d82b-4674-9387-e47f76f8601e}
#USBウェブカメラをマウント
$ vboxmanage controlvm 35cd756a-d82b-4674-9387-e47f76f8601e webcam attach .1
仮想マシンにUSBウェブカメラをマウントできたかどうかは上図[3.USBデバイスが追加された]のように仮想マシンのターミナル上でusbデバイスリストを表示することにより確認できます。
毎回VirtualBoxの起動毎に同様の設定を行うのは手間なのでVagrantfileに下のような記述を追加しておくとこの手順を省略できます。
## トリガーの実行タイミングを設定(この場合は "vagrant up" と "vagrant reload"時)
config.trigger.after [:up, :reload] do |trigger|
## uuidをvagrantの設定ファイルから読み込み
id = File.read(".vagrant\\machines\\default\\virtualbox\\id")
## 以下はトリガー実行時にコンソールへ出力するログなので省略可
trigger.info = "Mount webcam to #{id}"
## 以下はコンソール上で"vboxmanage controlvm #{id} webcam attach .1 "を実行するのと等価
trigger.run = {
inline: "vboxmanage controlvm #{id} webcam attach .1",
}
end
VirtualBox上の仮想マシンでUSBウェブカメラを動作させる
仮想マシンにUSBウェブカメラを認識させることができたので動作テストを行います。
参考
# ffmpegとv4l2-ctlのインストール
$ sudo apt-get install v4l-utils ffmpeg -y
# 利用できるUSBウェブカメラのデバイスリストを取得
$ v4l2-ctl --list-devices
VirtualBox Webcam - Logicool HD (usb-0000:00:06.0-1):
/dev/video0
# ffmpegを利用してv4l2形式,映像解像度:640x480,フレームレート:30fps,記録時間:5sec,/dev/video0のデバイスで録画する
$ ffmpeg -hide_banner -f v4l2 -t 3 -framerate 30 -video_size 640x480 -i /dev/video0 /vagrant/data/output.mp4
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 2272.982078, bitrate: N/A
Stream #0:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 640x480, -5 kb/s, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
No pixel format specified, yuvj422p for H.264 encoding chosen.
Use -pix_fmt yuv420p for compatibility with outdated media players.
### 各種ログ中略 ###
[libx264 @ 0x1689f00] ref P L0: 61.9% 23.0% 6.9% 7.3% 0.8%
[libx264 @ 0x1689f00] ref B L0: 94.6% 5.0% 0.4%
[libx264 @ 0x1689f00] ref B L1: 99.1% 0.9%
[libx264 @ 0x1689f00] kb/s:1284.7
# ファイル有無を確認
$ ls -ls /vagrant/data/
total 480
480 -rwxrwxrwx 1 vagrant vagrant 489172 Jun 30 13:44 output.mp4
- 実際の録画映像(Windows->Virtualbox)
Dockerコンテナ上でUSBウェブカメラを動作させる
Dockerを動かすVirtualBox上でUSBウェブカメラの認識、動作確認ができたので、ここから本番のDockerでの録画環境を構築していきます。
公式ドキュメントに従ってVirtualbox上にDocker-ceをインストールしておきます。
最小限の環境として以下の様なdockerfileを作成し、Dockerイメージのビルドを行います。
FROM ubuntu:18.04
RUN apt-get update && \
apt-get install -y \
v4l-utils \
ffmpeg
# Dockerイメージのビルド $ docker build -t webcam_sample:latest . # ビルドしたイメージの確認 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE webcam_sample latest e8df2049ae04 43 seconds ago 385MB
Dockerイメージのビルドが成功したのでDockerコンテナを起動し、
先程VirtualBox上で確認したようにビデオデバイスの確認を行っていきます。
# VirtualBox上の/dev/video0をDockerコンテナの/dev/video0へマウント、/vagrant/dataをDockerコンテナの/dataへマウント
$ docker run --rm -it --device=/dev/video0:/dev/video0 -v /vagrant/data:/data -e "TZ=Asia/Tokyo" webcam_sample:latest /bin/bash
## 以後Dockerコンテナのコンソールにて実行
# ビデオデバイスの確認
$ v4l2-ctl --list-devices
VirtualBox Webcam - Logicool HD (usb-0000:00:06.0-1):
/dev/video0
# 録画実行
$ ffmpeg -hide_banner -f v4l2 -t 5 -framerate 30 -video_size 640x480 -i /dev/video0 /data/docker.mp4
[mjpeg @ 0x56051c0d69e0] unable to decode APP fields: Invalid data found when processing input
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 9778.985765, bitrate: N/A
Stream #0:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
Stream mapping:
Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (libx264))
### 中略 ###
[libx264 @ 0x56051c0d9fc0] Weighted P-Frames: Y:22.0% UV:22.0%
[libx264 @ 0x56051c0d9fc0] ref P L0: 53.8% 11.0% 23.8% 10.7% 0.7%
[libx264 @ 0x56051c0d9fc0] ref B L0: 70.0% 21.5% 8.5%
[libx264 @ 0x56051c0d9fc0] ref B L1: 95.9% 4.1%
[libx264 @ 0x56051c0d9fc0] kb/s:780.91
$ ls /data/
docker.mp4 output.mp4
WindowsホストにつないだUSBウェブカメラでDockerコンテナから録画ができたことが確認できました。
- 実際の録画映像(Windows->Virtualbox->Docker)
最後に
Docker for Windowsが使えなかったこともあり、ラズパイを用意してそこにカメラモジュールを繋いだほうが楽だったのではという結果になってしまいました。
しかし、当初の予定であったWindowsホストに接続したUSBカメラをDockerコンテナ上で認識・動作させることについては成功したこと、
Vagrantfileでのtrigger設定など新しいことも試せたので結果的にはやってよかったかなと思います。
CONTACT
お問い合わせ
あなたの「想い」に挑戦します。
どうぞお気軽にお問い合わせください。
受付時間:平日9:00〜18:00 日・祝日・弊社指定休業日は除く






