I’m currently trying to build a voice assistant with Python when I ran into a problem. I’m using porcupine/picovoice for wakeword detection and then I call a function that recognizes everything I say as soon as I call it.
This is the function:
def recognizevoicecommand(): try: r = sr.Recognizer() print("A moment of silence, please...") with sr.Microphone() as source: time.sleep(2) r.adjust_for_ambient_noise(source) print("Set minimum energy threshold to {}".format(r.energy_threshold)) while True: print("Say something!") with m as source: time.sleep(2) print("Now!") audio = r.listen(source) print("Got it! Now to recognize it...") try: # recognize speech using Google Speech Recognition value = r.recognize_google(audio) print(value) return value break except sr.UnknownValueError(): print("OOps") break except KeyboardInterrupt: pass
If i just call the function alone, it works perfectly fine, recognizes what I say and then prints it out.
But the problem is that as soon as I use it together with the wakeword detector, I get spammed with Overflow – reader is not reading fast enough after A moment of silence, please… is printed out.
This is the wakeword detection code, works fine on it’s own as well as in the script, the problem seems to be in the recognizing part
porcupine = pvporcupine.create(access_key = accesskey, keywords=['computer']) recorder = PvRecorder(device_index = 0, frame_length = porcupine.frame_length) recorder.start() while True: pcm = recorder.read() result = porcupine.process(pcm) if(result >= 0): print("Keyword detected") print(recognizevoicecommand()) except pvporcupine.PorcupineInvalidArgumentError as e: print("One or more arguments provided to Procupine is invalid!") raise e except pvporcupine.PorcupineActivationError as e: print("Accesskey denied.") raise e except pvporcupine.PorcupineActivationLimitError as e: print("Accesskey has reached it's temporary device limit.") raise e except pvporcupine.PorcupineActivationRefusedError as e: print("Accesskey refused.") raise e except pvporcupine.PorcupineActivationThrottledError as e: print("Accesskey has been throttled.") raise e except pvporcupine.PorcupineError as e: print("Failed to initialize Porcupine.") raise e except KeyboardInterrupt: print("Stopping") finally: if porcupine is not None: porcupine.delete() if recorder is not None: recorder.delete()
I am honestly clueless why its not working. Hope to find a solution tho!
Advertisement
Answer
I’m working on a similar task and running into the same issue. I’ve found that the solution is to avoid using two different means of recording audio.
The PvRecorder class represents the recorded data as signed integers.
pcm = recorder.read() result = porcupine.process(pcm)
This is different AFAIK than how wav data is typically stored in an audio file. If you look to how PvRecorder saves wav files, you can see they use the struct module:
sp = struct.pack("h" * len(pcm), *pcm)
You can use that to construct the audio file to pass along. I’m using it with Vosk and it works great!
if self.rec.AcceptWaveform(sp): res = json.loads(self.rec.Result()) if res["text"] != "": print(res["text"])