Ubuntu 20.04 で Web カメラのオーディオデバイス番号を固定化

Linux に USB で Web カメラを接続した際、Linux を再起動しても Web カメラのオーディオデバイスが一定の値に固定化されるようにしてみます。

Web カメラのオーディオデバイスの番号を固定化する目的としては、FFmpeg で Web カメラの映像とマイクの音声をリアルタイムにエンコードする際に、FFmpeg のオプションとして Web カメラのオーディオデバイスを “hw:0,0” のように固定化するためです。

例えば、マザーボードのオンボードのサウンドデバイスと Web カメラのマイクのように Linux PC が復数のオーディオデバイスを持っている場合、/proc/asound 下に card0, card1 ディレクトリができます。しかし、何も設定していない場合、OS を起動する度にオーディオデバイスと cardX の割り当て番号 (X は整数) が異なってしまう場合があります。つまり、オーディオデバイスと cardX の割り当てが固定化されない状況が発生します。

OS は Ubuntu 20.04 です。マザーボードは B85M-E です。マザーボードにはビデオカードとして NVIDIA GeForce GTX 1050 を接続しています。Web カメラは Logicool C910 です。

Web カメラ接続前

まず、dmidecode コマンドで、マザーボードの製品名を確認してみます。ASUSTeK の B85M-E でした。

$ sudo dmidecode -t 2

# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.

Handle 0x0002, DMI type 2, 15 bytes
Base Board Information
	Manufacturer: ASUSTeK COMPUTER INC.
	Product Name: B85M-E
	Version: Rev X.0x
	Serial Number: 
	Asset Tag: To be filled by O.E.M.
	Features:
		Board is a hosting board
		Board is replaceable
	Location In Chassis: To be filled by O.E.M.
	Chassis Handle: 0x0003
	Type: Motherboard
	Contained Object Handles: 0

続いて、aplay コマンドを実行してみます。オーディオを再生するハードウェアの情報が表示されます。

$ aplay -l

**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC887-VD Analog [ALC887-VD Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

/proc/asound を確認してみます。card0, card1 が存在していることがわかります。

$ ls -al /proc/asound
total 0
dr-xr-xr-x   6 root root 0  7月 11 22:05 .
dr-xr-xr-x 318 root root 0  7月 11 22:05 ..
dr-xr-xr-x   5 root root 0  7月 11 22:05 card0
dr-xr-xr-x   5 root root 0  7月 11 22:05 card1
-r--r--r--   1 root root 0  7月 11 22:09 cards
-r--r--r--   1 root root 0  7月 11 22:10 devices
-r--r--r--   1 root root 0  7月 11 22:10 hwdep
-r--r--r--   1 root root 0  7月 11 22:10 modules
lrwxrwxrwx   1 root root 5  7月 11 22:10 NVidia -> card1
dr-xr-xr-x   2 root root 0  7月 11 22:10 oss
lrwxrwxrwx   1 root root 5  7月 11 22:10 PCH -> card0
-r--r--r--   1 root root 0  7月 11 22:10 pcm
dr-xr-xr-x   2 root root 0  7月 11 22:10 seq
-r--r--r--   1 root root 0  7月 11 22:10 timers
-r--r--r--   1 root root 0  7月 11 22:10 version

/proc/asound/cards を確認してみます。

$ cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xf7110000 irq 32
 1 [NVidia         ]: HDA-Intel - HDA NVidia
                      HDA NVidia at 0xf7080000 irq 17

/proc/asound/devices を確認してみます。

$ cat /proc/asound/devices
  2: [ 0- 0]: digital audio playback
  3: [ 0- 0]: digital audio capture
  4: [ 0- 2]: digital audio capture
  5: [ 0- 0]: hardware dependent
  6: [ 0]   : control
  7: [ 1- 3]: digital audio playback
  8: [ 1- 7]: digital audio playback
  9: [ 1- 8]: digital audio playback
 10: [ 1- 0]: hardware dependent
 11: [ 1]   : control
 33:        : timer

/proc/asound/pcm を確認してみます。

$ cat /proc/asound/pcm
00-00: ALC887-VD Analog : ALC887-VD Analog : playback 1 : capture 1
00-02: ALC887-VD Alt Analog : ALC887-VD Alt Analog : capture 1
01-03: HDMI 0 : HDMI 0 : playback 1
01-07: HDMI 1 : HDMI 1 : playback 1
01-08: HDMI 2 : HDMI 2 : playback 1

arecord コマンドを実行してみます。オーディオをキャプチャするハードウェアの情報が表示されます。

$ arecord -l

**** List of CAPTURE Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC887-VD Analog [ALC887-VD Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 2: ALC887-VD Alt Analog [ALC887-VD Alt Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

/proc/asound/modules を確認してみます。

$ cat /proc/asound/modules
 0 snd_hda_intel
 1 snd_hda_intel

Web カメラ接続後

Web カメラを USB でマザーボードに接続後、lsusb を実行してみます。

$ lsusb
Bus 003 Device 006: ID 046d:0821 Logitech, Inc. HD Webcam C910

dmesg を実行してみます。

[  499.613082] usb 3-3: new high-speed USB device number 5 using xhci_hcd
[  504.924948] usb 3-3: unable to read config index 0 descriptor/all
[  504.924958] usb 3-3: can't read configurations, error -110
[  505.260871] usb 3-3: new high-speed USB device number 6 using xhci_hcd
[  505.680214] usb 3-3: New USB device found, idVendor=046d, idProduct=0821, bcdDevice= 0.10
[  505.680221] usb 3-3: New USB device strings: Mfr=0, Product=0, SerialNumber=1
[  505.680224] usb 3-3: SerialNumber: 
[  505.716113] videodev: Linux video capture interface: v2.00
[  506.151191] usbcore: registered new interface driver snd-usb-audio
[  506.151321] uvcvideo: Found UVC 1.00 device <unnamed> (046d:0821)
[  506.189812] uvcvideo 3-3:1.2: Entity type for entity Extension 4 was not initialized!
[  506.189817] uvcvideo 3-3:1.2: Entity type for entity Processing 2 was not initialized!
[  506.189820] uvcvideo 3-3:1.2: Entity type for entity Camera 1 was not initialized!
[  506.189823] uvcvideo 3-3:1.2: Entity type for entity Extension 5 was not initialized!
[  506.189825] uvcvideo 3-3:1.2: Entity type for entity Extension 6 was not initialized!
[  506.189826] uvcvideo 3-3:1.2: Entity type for entity Extension 7 was not initialized!
[  506.189828] uvcvideo 3-3:1.2: Entity type for entity Extension 8 was not initialized!
[  506.189951] input: UVC Camera (046d:0821) as /devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3:1.2/input/input22
[  506.190165] usbcore: registered new interface driver uvcvideo
[  506.190167] USB Video Class driver (1.1.1)

v4l-utils をインストールし、v4l2-ctl で Web カメラのデバイス名を確認してみます。

sudo apt install v4l-utils

$ v4l2-ctl --list-devices
UVC Camera (046d:0821) (usb-0000:00:14.0-9):
	/dev/video0
	/dev/video1
	/dev/media0

$ v4l2-ctl -d 0 -D
Driver Info:
	Driver name      : uvcvideo
	Card type        : UVC Camera (046d:0821)
	Bus info         : usb-0000:00:14.0-9
	Driver version   : 5.4.44
	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            : UVC Camera (046d:0821)
	Serial           : 29249F90
	Bus info         : usb-0000:00:14.0-9
	Media version    : 5.4.44
	Hardware revision: 0x00000010 (16)
	Driver version   : 5.4.44
Interface Info:
	ID               : 0x03000002
	Type             : V4L Video
Entity Info:
	ID               : 0x00000001 (1)
	Name             : UVC Camera (046d:0821)
	Function         : V4L2 I/O
	Flags         : default
	Pad 0x01000007   : 0: Sink
	  Link 0x0200001c: from remote pad 0x100000a of entity 'Extension 4': Data, Enabled, Immutable

/proc/asound を確認してみます。card2 が追加されていました。

~$ ls -al /proc/asound
total 0
dr-xr-xr-x   7 root root 0  7月 11 22:05 .
dr-xr-xr-x 305 root root 0  7月 11 22:05 ..
dr-xr-xr-x   5 root root 0  7月 11 22:05 card0
dr-xr-xr-x   5 root root 0  7月 11 22:05 card1
dr-xr-xr-x   3 root root 0  7月 11 22:13 card2
-r--r--r--   1 root root 0  7月 11 22:09 cards
-r--r--r--   1 root root 0  7月 11 22:10 devices
-r--r--r--   1 root root 0  7月 11 22:10 hwdep
-r--r--r--   1 root root 0  7月 11 22:10 modules
lrwxrwxrwx   1 root root 5  7月 11 22:10 NVidia -> card1
dr-xr-xr-x   2 root root 0  7月 11 22:10 oss
lrwxrwxrwx   1 root root 5  7月 11 22:10 PCH -> card0
-r--r--r--   1 root root 0  7月 11 22:10 pcm
dr-xr-xr-x   2 root root 0  7月 11 22:10 seq
-r--r--r--   1 root root 0  7月 11 22:10 timers
lrwxrwxrwx   1 root root 5  7月 11 22:17 U0x46d0x821 -> card2
-r--r--r--   1 root root 0  7月 11 22:10 version

/proc/asound/cards を確認してみます。Web カメラの番号は 2 に設定されていました。

$ cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xf7110000 irq 32
 1 [NVidia         ]: HDA-Intel - HDA NVidia
                      HDA NVidia at 0xf7080000 irq 17
 2 [U0x46d0x821    ]: USB-Audio - USB Device 0x46d:0x821
                      USB Device 0x46d:0x821 at usb-0000:00:14.0-3, high speed

/proc/asound/devices を確認してみます。

$ cat /proc/asound/devices
  2: [ 0- 0]: digital audio playback
  3: [ 0- 0]: digital audio capture
  4: [ 0- 2]: digital audio capture
  5: [ 0- 0]: hardware dependent
  6: [ 0]   : control
  7: [ 1- 3]: digital audio playback
  8: [ 1- 7]: digital audio playback
  9: [ 1- 8]: digital audio playback
 10: [ 1- 0]: hardware dependent
 11: [ 1]   : control
 12: [ 2- 0]: digital audio capture
 13: [ 2]   : control
 33:        : timer

/proc/asound/pcm を確認してみます。

$ cat /proc/asound/pcm
00-00: ALC887-VD Analog : ALC887-VD Analog : playback 1 : capture 1
00-02: ALC887-VD Alt Analog : ALC887-VD Alt Analog : capture 1
01-03: HDMI 0 : HDMI 0 : playback 1
01-07: HDMI 1 : HDMI 1 : playback 1
01-08: HDMI 2 : HDMI 2 : playback 1
02-00: USB Audio : USB Audio : capture 1

arecord コマンドを実行してみます。オーディオをキャプチャするハードウェアで card 2 として Web カメラが設定されていました。

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC887-VD Analog [ALC887-VD Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 2: ALC887-VD Alt Analog [ALC887-VD Alt Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: U0x46d0x821 [USB Device 0x46d:0x821], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

/proc/asound/modules を確認してみます。Web カメラを示す snd_usb_audio には 2 が設定されていました。

$ cat /proc/asound/modules
 0 snd_hda_intel
 1 snd_hda_intel
 2 snd_usb_audio

Web カメラには必ず 0 が設定されるようにしてみます。例えば下記のように /etc/modprobe.d の下に conf ファイルを作成してみます。

sudo sh -c "echo 'options snd slots=snd_usb_audio,snd_hda_intel,snd_hda_intel' >> /etc/modprobe.d/alsa-base.conf"
sudo sh -c "echo 'options snd_usb_audio index=0' >> /etc/modprobe.d/alsa-base.conf"
sudo sh -c "echo 'options snd_hda_intel index=1' >> /etc/modprobe.d/alsa-base.conf"
sudo sh -c "echo 'options snd_hda_intel index=2' >> /etc/modprobe.d/alsa-base.conf"

作成後、OS を再起動してみます。再起動後 /proc/asound/cards を確認すると、Web カメラのオーディオデバイスの番号に 0 が設定されていました。

$ cat /proc/asound/cards
 0 [U0x46d0x821    ]: USB-Audio - USB Device 0x46d:0x821
                      USB Device 0x46d:0x821 at usb-0000:00:14.0-9, high speed
 1 [NVidia         ]: HDA-Intel - HDA NVidia
                      HDA NVidia at 0xf7080000 irq 17
 2 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xf7110000 irq 32

/proc/asound/modules を確認してみます。Web カメラを示す snd_usb_audio には 0 が設定されていました。

$ cat /proc/asound/modules
 0 snd_usb_audio
 1 snd_hda_intel
 2 snd_hda_intel

/proc/asound/card0/pcm0c/info を確認してみます。Web カメラのオーディオデバイスの card は 0, device は 0 でした。

$ cat /proc/asound/card0/pcm0c/info

card: 0
device: 0
subdevice: 0
stream: CAPTURE
id: USB Audio
name: USB Audio
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1

以上により、FFmpeg で Web カメラの映像とマイクの音声をリアルタイムにエンコードする際に、FFmpeg のオプションとして Web カメラのオーディオデバイスを “hw:0,0″ のように固定化することができます。”hw:X,Y” において,X は card, Y は device を指すようです。また、”hw:0,0″ は “default” として設定してもよさそうです。

なお、Web カメラの映像とマイクの音声をキャプチャしたい場合、キャプチャを実行するユーザーを video グループと audio グループに追加しておく必要があります。追加後、設定を反映させたい場合は、いったんログオフしてログインし直すか、OS を再起動する必要があります。

sudo gpasswd -a $USER video
sudo gpasswd -a $USER audio

Web カメラのマイクの音声をキャプチャしようとしているユーザーが audio グループに所属していない場合、FFmpeg では下記のようなエラーが表示されます。

ALSA lib pcm_hw.c:1401:(_snd_pcm_hw_open) Invalid value for card
[alsa @ 0x1217140] cannot open audio device hw:0,0 (No such file or directory)
hw:0,0: Input/output error