Issue setting up Snowboy hotword detection alongside python SpeechRecognition library

Viewed 961

I want to use both the Snowboy hotword detection library and SpeechRecognition library in a python project. However, I've been encountering a number of various errors trying to get the two to play nice together.

Initially, I had set it up in such a way that Snowboy's callback function would start SpeechRecognition's listen function to take in the audio after the hotword was detected. However, both libraries seem to lock access to the microphone when each of their respective instances are created. As such this code would throw an error from PyAudio complaining about SpeechRecognition trying to access a microphone already being used (by Snowboy).

I tried a couple ways to get around this issue including using multithreading/multiprocessing and deleting each microphone instance right after they were done being used then recreating them when they were needed again (pretty ugly). I didn't get any luck with any of these workarounds though.

My most recent attempt was to use SpeechRecognition's built in Snowboy hotword implementation. I had known about this feature but avoided it till now since I preferred being able to control what happened between the hotword detection and STT translation. Doing this got me past the issue of sharing a microphone between two libraries, but now the hotword models I train from Snowboy's site don't seem to work as well as they should be, at all even. I played around with both creating different models with different microphones and adjusting the sensitivity setting to no avail.

At this point I considering revisiting the idea of deleting/recreating microphone instances to go back to using Snowboy's library for hotword detection rather than the built in implementation in SpeechRecognition as I feel the two methods are different enough to be causing my current issue with the models. Before switching the SpeechRecognition's implementation, hotword detection worked far better.

A couple of things to note:

  • running on a Raspberry Pi 3 B+ w/ Raspbian
  • my current code can be found here
  • Snowboy library is copied directly into the repo. It's implementation can be found here
  • SpeechRecognition implementation of Snowboy hotword can be found here

If anyone wants to see logs, error outputs, etc. let me know.

Thanks for any and all help.

2 Answers

To anyone who might be having the same or similar issues, I came across the solution. All of the methods I tried ultimately didn't work, but I discovered that the functionality I was looking for was already built into the Snowboy library. However, the prebuilt binaries available for direct download are outdated and don't have this functionality yet. Therefore, to get the functionality I described, you would have to go through the process of compiling your own custom binary with the instructions in the README on Snowboy's GitHub repo.

Making this change immediately fixed the issues I was having and made me able to move on with my project.

Hope this helps anyone else that might be stuck on this.

you can combine snowboy hotword detection with google-assistant-api. below is a working example of listening to a number of hotwords connected to google's assistant (running on raspberry pi 4 with AIY VOICE IMAGE from https://github.com/google/aiyprojects-raspbian/releases/tag/v20191113)

import locale
import logging
import signal
from aiy.assistant.grpc import AssistantServiceClientWithLed
from aiy.board import Board
import mod.snowboydecoder as snowboydecoder

models = ['/home/pi/snowboy/resources/wake_word1.umdl',
      '/home/pi/snowboy/resources/wake_word12.umdl']

def main():
    logging.basicConfig(level=logging.DEBUG)
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(0))

    detector = snowboydecoder.HotwordDetector(models, sensitivity=0.5)
    with Board() as board:
        assistant = AssistantServiceClientWithLed(
            board=board,
            volume_percentage=100,
            language_code=locale.getdefaultlocale())
        while True:
            logging.info('say any of your pre-defined hotwords to start the     assisteant')
            detector.start()
            logging.info('assistant is now listening :)')
            assistant.conversation()

if __name__ == '__main__':
    main()
Related