Python: OSError: [Errno -9985] Устройство недоступно при использовании Snowboy и SpeechRecognition на Raspberry PI 3B+

Я строю личного помощника на моем 3B+. Сейчас я пытаюсь использовать Snowboy для обнаружения моего горячего слова (работает безупречно), а затем, после обнаружения горячего слова, использовать SpeechRecognizer для получения голосовой команды. Обнаружение горячих слов работает нормально, ошибка возникает при вызове sr.Microphone().

Пример кода:

import speech_recognition as sr
import snowboydecoder

def detected_callback():
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print('Ready...')
        r.adjust_for_ambient_noise(source, duration=.2)
        audio = r.listen(source)

    try:
        command = r.recognize_google(audio).lower()
        print('You said: ' + command + '\n')

    except sr.UnknownValueError:
        print('Your last command couldn\'t be heard')
        comand = None

detector = snowboydecoder.HotwordDetector("SnowboyDependencies/Ancilla.pmdl", sensitivity=.5, audio_gain=1)
detector.start(detected_callback)

Я получаю следующий вывод:

INFO:snowboy:Keyword 1 detected at time: 2020-03-24 21:53:35
Expression 'ret' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1736
Expression 'AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1904
Expression 'PaAlsaStreamComponent_Initialize( &self->capture, alsaApi, inParams, StreamDirection_In, NULL != callback )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2171
Expression 'PaAlsaStream_Initialize( stream, alsaHostApi, inputParameters, outputParameters, sampleRate, framesPerBuffer, callback, streamFlags, userData )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2840
Traceback (most recent call last):
  File "sttTest.py", line 43, in <module>
    detector.start(detected_callback)
  File "/home/pi/AncillaFiles/SnowboyDependencies/snowboydecoder.py", line 221, in start
    callback()
  File "sttTest.py", line 27, in detected_callback
    with sr.Microphone(device_index = 2, sample_rate = 44100, chunk_size = 512) as source:
  File "/home/pi/.local/lib/python3.7/site-packages/speech_recognition/__init__.py", line 141, in __enter__
    input=True,  # stream is an input stream
  File "/usr/local/lib/python3.7/dist-packages/pyaudio.py", line 750, in open
    stream = Stream(self, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/pyaudio.py", line 441, in __init__
    self._stream = pa.open(**arguments)
OSError: [Errno -9985] Device unavailable

Снежок работает нормально. Программа работает, как и ожидалось, пока не будет обнаружено горячее слово. Я думаю, это должно быть как-то связано с тем, что Snowboy и SpeechRecognition пытаются использовать микрофон. Также обратите внимание, что SpeechRecognition отлично работает сам по себе. Если я создам программу, которая просто использует SpeechRecognition, а не Snowboy, она будет работать, как и ожидалось.

Я использую Python3 на Raspberry Pi 3b+ с Raspbian Buster.

Если я могу предоставить дополнительную информацию, пожалуйста, дайте мне знать.


person marc.soda    schedule 24.03.2020    source источник


Ответы (2)


Решение состоит в том, чтобы завершить работу Snowboy перед инициализацией микрофона. Пример:

import speech_recognition as sr
import snowboydecoder

def detected_callback():
    detector.terminate() #change here
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print('Ready...')
        r.adjust_for_ambient_noise(source, duration=.2)
        audio = r.listen(source)

    try:
        command = r.recognize_google(audio).lower()
        print('You said: ' + command + '\n')

    except sr.UnknownValueError:
        print('Your last command couldn\'t be heard')
        comand = None

detector = snowboydecoder.HotwordDetector("SnowboyDependencies/Ancilla.pmdl", sensitivity=.5, audio_gain=1)
detector.start(detected_callback)
person marc.soda    schedule 25.03.2020

Проблема в том, что оба (Snowboy и SpeechRec) пытаются подключиться к вашему микрофону. И вторая попытка подключения будет отклонена.

У меня была такая же проблема несколько дней назад. Решение от @Mezex прекрасное, в моем случае требуется слишком много времени, чтобы закрыть Snowboy и открыть SpeechRec (около 2 или 3 секунд, пока он не будет готов к прослушиванию)

Мое решение относится к ALSA. Существует плагин с именем dsnoop, который чем-то похож на файл устройства, который может вызываться несколькими программами.

Файл /etc/asound.config решает, что делать со звуком для вашей дырочной операционной системы. Если вы измените его на:

defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    slave.pcm "hw:name_of_your_speaker"
    ipc_key 555555
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:name_of_your_Mic"
        channels 2
    }
    ipc_key 666666
}

И удалите свой файл ~/asoundrc, должно работать.

Вы получите имя своего микрофона по arecord -l В моем случае это "wm8960soundcard"

pcm.!default вызывается по умолчанию. Он ссылается на входной поток (ваш микрофон) на caputre, который ссылается на array. И это через type dsnoop, вызываемый несколькими задачами одновременно.

Взгляните на https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html, там есть список всех плагинов

Я знаю, что это немного сложно, но для меня это лучшее решение. Надеюсь, это помогло.

person Tobi    schedule 11.04.2020