みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

python-opencvでWebカメラを一覧から取得する

python-opencvVideoCapture(index)を使えば,Webカメラを気軽に操作できますが,複数のWebカメラを扱う時にindexをどうやって指定するかが問題となります.

MacOSならば,system_profilerコマンドがありますので,これを使えば正しいindexを取得できます.

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
% python3 --version
Python 3.9.7

system_profilerコマンドにはSPCameraDataTypeオプションがあり,カメラ情報のみを取得します. -jsonを指定することで,出力がjson形式となり,pythonで扱いやすくなります*1.みーのiMacに別のWebカメラを接続して実行したところ,以下のような出力を得ました.

{
  "SPCameraDataType" : [
    {
      "_name" : "FaceTime HD Camera (Built-in)",
      "spcamera_model-id" : "UVC Camera VendorID_1452 ProductID_34065",
      "spcamera_unique-id" : "0x144000xxxxxxxxxxxx"
    },
    {
      "_name" : "USB  Camera",
      "spcamera_model-id" : "UVC Camera VendorID_xxxx ProductID_xxxx",
      "spcamera_unique-id" : "0x1434300xxxxxxxxxxxxx"
    }
  ]
}

これをpythonで扱えるようにするため,関数を作りました.

import subprocess
from typing import Optional

def get_camera_id(name: str) -> Optional[int]:
    r = subprocess.run(
        ["system_profiler", "SPCameraDataType", "-json"],
        capture_output=True,
        text=True,
    )
    if r.returncode != 0:
        return None
    d = json.loads(r.stdout)
    for i, camera in enumerate(d.get("SPCameraDataType", [])):
        if name in camera.get("spcamera_model-id", ""):
            return i
    return None

上記のget_camera_id(name: str)を使えば,検索するnameを含むカメラのindexを取得できます.エラーや該当するカメラがない場合はNoneを返します.例えば,FaceTime HD Camera (Built-in)を検索します.

>>> get_camera_id("VendorID_1452")
0

なお,1452はAppleのUSB vendor idの10進法の表記です*2