LoginSignup
2
3

More than 3 years have passed since last update.

webカメラを複数台挿した時、どれが/dev/video?? なのかを確認する方法

Last updated at Posted at 2020-09-28

問題

webカメラを1台だけ挿すのなら、通常は/dev/video0に繋げばいいと思う


$ fswebcam -d /dev/video0 a.jpg
# またはデフォルトで/dev/video0なので
$ fswebcam a.jpg

しかし、2台以上だとどのカメラが/dev/video0なのか2なのか何なのかわからなくなる。

解決方法

v4l2-ctlを使うとこういうリストが出力できる。

raspberryPiでの例
$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
    /dev/video10
    /dev/video11
    /dev/video12

bcm2835-isp (platform:bcm2835-isp):
    /dev/video13
    /dev/video14
    /dev/video15
    /dev/video16

BUFFALO BSW32KM03 USB PC Camera (usb-20980000.usb-1.3):
    /dev/video0
    /dev/video1

UVC Camera (046d:0825) (usb-20980000.usb-1.5):
    /dev/video2
    /dev/video3

ここで注目するのは、カメラには(usb-20980000.usb-1.5)的なのがついているということ。
そしてこのusb-1.5の部分は物理的なUSBポートに紐付けられている(参考)。

なので、webカメラを常時挿したままであれば、そのカメラのここで言うUSB番号が固定されるので、その下に書いてある最初のパス(/dev/video*)を使うとカメラの画像が取れる(もう一方はメタデータ?らしい)。

これらを踏まえての簡単なrubyスクリプト

require "./video_paths"
VideoPaths.paths # => {"1.3"=>"/dev/video0", "1.5"=>"/dev/video2"}
video_paths.rb
require "memoist"
require "active_support/core_ext/object/blank"

class VideoPaths
  USB_NUMBER_REG = /\.usb\-([\d\.]+)/

  class << self
    extend Memoist
    def paths
      new.to_h
    end
    memoize :paths
  end

  def initialize
    @output = clean_output(`v4l2-ctl --list-devices`)
  end

  def to_h
    camera_names.to_h do |camera_name|
      key, valid_path, *other_paths = group_by_device[camera_name]
      [extract_usb_number(camera_name), valid_path]
    end
  end

  private

  attr_reader :output

  def group_by_device
    key = :not_yet
    output.group_by do |line|
      key = line if line.end_with?(":")
      key
    end
  end

  # BUFFALO BSW32KM03 USB PC Camera (usb-20980000.usb-1.3):
  #                         ^^^^^^^^
  def camera_names
    group_by_device.keys.select { |key| key.match?(/camera/i) }
  end

  # BUFFALO BSW32KM03 USB PC Camera (usb-20980000.usb-1.3):
  #                                               ^^^^^^^^
  def extract_usb_number(camera_name)
    camera_name.match(USB_NUMBER_REG)[1]
  end

  def clean_output(text)
    text.lines.collect(&:strip).delete_if(&:blank?)
  end
end
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3