Reputation: 428
I am building a personal assistant on my 3B+. What I am trying to do now is use Snowboy to detect my hotword (works flawlessly), then after the hotword is detected, use SpeechRecognizer to receive a voice command. Hotword detection works fine, the error happens when sr.Microphone() is called.
Example Code:
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)
I receive the following output:
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 works fine. The program runs as expected until the hotword is detected. I think it must have something to do with the fact that Snowboy and SpeechRecognition are trying to use the microphone. Also note that SpeechRecognition works fine on its own. If I create a program that just uses SpeechRecognition and not Snowboy, it works as expected.
I am using Python3 on the Raspberry Pi 3b+ running Raspbian Buster.
If I can provide more information, please let me know.
Upvotes: 1
Views: 1469
Reputation: 11
Tho Problem is, that both (Snowboy and SpeechRec) try to connect to your Microphone. And the second connection-try will be denied.
I had the same Problem a few days ago. The solution from @Mezex is fine, takes in my case just to long to close Snowboy and open SpeechRec (about 2 or 3 sec till it is ready to listen)
My solution referes to ALSA. There is a plugin named dsnoop
, which is kind of similiar to a device file, which can be called by multiple programs.
The file /etc/asound.config
decides what to do with the sound for your hole operating system. If you change it to:
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
}
And remove your ~/asoundrc
file, it should work.
You will get the name of your Mic by arecord -l
In my case it is "wm8960soundcard"
The pcm.!default
is called by default. It referes for an input-stream (your Mic) to caputre
, which referes to array
. And this is through the type dsnoop
callable by multiple tasks simultaneously.
Have a look at https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html, there are all plugins listet
I know it's a bit complicated, but for me it is the best solution. Hope it helped.
Upvotes: 1
Reputation: 428
The solution is to terminate snowboy before initializing the microphone Ex:
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)
Upvotes: 3