Support selecting microphone by name

Normally Mycroft will use the default PortAudio input device as the
microphone input for the user.  However in some cases there is reason
to specify a different input.

The "device_index" under the "listener" section in mycroft.conf has
always allowed a user to select the microphone explicitly.  But on
some systems the indices can change from reboot to reboot.  So this
adds the "device_name" setting.  If it exists (and the "device_index"
has not been specified explicitly), a regex match will be run against
the PortAudio device names.

When "device_name" is used, the voice.log will contain a listing of
the devices as they are tested.  This can be used to debug if a
name isn't matching as expected.

EXAMPLES:
/etc/mycroft/mycroft.conf
```
{
    "listener": {
        "device_name": "aawsrc"
    }
}
```
Would find a match against "aawsrc" or "aawsrcplug".  To force a specific
match, you can use a regex such as "aawsrc$".

/etc/mycroft/mycroft.conf
```
{
    "listener": {
        "device_index": 2
    }
}
```
The PortAudio device index specified will be used.

Names and indexes for PortAudio are difficult to guess.  The simplest way to
view them is either enter a value for "device_name" and look at the names
which appear in the log when starting Mycroft, or to run a simple program
such as:
```python
import pyaudio

pa = pyaudio.PyAudio()
for i in range(pa.get_device_count()):
    dev = pa.get_device_info_by_index(i)
    print((i, dev['name'], dev['maxInputChannels']))
```
pull/1936/head
Steve Penrod 2019-01-07 23:02:59 -06:00 committed by Åke Forslund
parent e08075dd61
commit 2557637591
2 changed files with 27 additions and 1 deletions

View File

@ -16,6 +16,8 @@ import time
from threading import Thread
import sys
import speech_recognition as sr
import pyaudio
import re
from pyee import EventEmitter
from requests import RequestException, HTTPError
from requests.exceptions import ConnectionError
@ -225,11 +227,29 @@ class RecognizerLoop(EventEmitter):
self.lang = config.get('lang')
self.config = config.get('listener')
rate = self.config.get('sample_rate')
device_index = self.config.get('device_index')
if not device_index:
device_name = self.config.get('device_name')
if device_name:
# Search for an input matching given name/pattern
LOG.info('Searching for input device: '+str(device_name))
LOG.debug('Devices: ')
pa = pyaudio.PyAudio()
pattern = re.compile(device_name)
for i in range(pa.get_device_count()):
dev = pa.get_device_info_by_index(i)
LOG.debug(' '+str(dev['name']))
if dev['maxInputChannels'] and pattern.match(dev['name']):
LOG.debug(' ^-- matched')
device_index = i
break
LOG.debug('Using microphone (None = default): '+str(device_index))
self.microphone = MutableMicrophone(device_index, rate,
mute=self.mute_calls > 0)
# FIXME - channels are not been used
# TODO:19.02 - channels are not been used, remove from mycroft.conf
# and from code.
self.microphone.CHANNELS = self.config.get('channels')
self.wakeword_recognizer = self.create_wake_word_recognizer()
# TODO - localization

View File

@ -158,6 +158,12 @@
"url": "https://training.mycroft.ai/precise/upload"
},
// Override as SYSTEM or USER to select a specific microphone input instead of
// the PortAudio default input.
// "device_name": "somename", // can be regex pattern or substring
// or
// "device_index": 12,
// Stop listing to the microphone during playback to prevent accidental triggering
// This is enabled by default, but instances with good microphone noise cancellation
// can disable this to listen all the time, allowing 'barge in' functionality.