diff --git a/whisper-2023/hotwords.py b/whisper-2023/hotwords.py new file mode 100644 index 0000000..9c9c23d --- /dev/null +++ b/whisper-2023/hotwords.py @@ -0,0 +1,104 @@ +import speech_recognition as sr +import time +import threading +import queue +import signal +import sys +from os import environ + +def main(): + managerToParserQ = queue.Queue(maxsize=1) + readerToParserQ = queue.Queue(maxsize=10) + parserToReactorQ = queue.Queue(maxsize=10) + threads = [ + Manager(managerToParserQ), + Reader(managerToParserQ, readerToParserQ), + Parser(readerToParserQ, parserToReactorQ), + ] + [t.start() for t in threads] + while True: + got = parserToReactorQ.get() + if not got: + break + print(got) + [t.join() for t in threads] + +def log(*args): + print(">", *args, file=sys.stderr) + +class Manager(threading.Thread): + def __init__(self, outq): + threading.Thread.__init__(self) + self.outq = outq + inq = queue.Queue(maxsize=1) + def catcher(sig, frame): + inq.put(None) + self.inq = inq + signal.signal(signal.SIGINT, catcher) + + def run(self): + log("Manager.run: start") + self.inq.get() + self.outq.put(None) + log("Manager.run: stop") + +class Reader(threading.Thread): + def __init__(self, inq, outq): + threading.Thread.__init__(self) + self.name = environ.get("MIC_NAME", "pulse_monitor") + self.inq = inq + self.outq = outq + + def run(self): + log("Reader.run: start") + idx = [ + idx for idx,v in enumerate( + sr.Microphone.list_microphone_names(), + ) if v in self.name.split(",") + ][0] + with sr.Microphone(device_index=idx) as mic: + while not self.should_stop(): + try: + self.outq.put(self._run(mic)) + except Exception as e: + log("Reader.run: error:", e) + self.outq.put(None) + log("Reader.run: stop") + + def should_stop(self): + return not self.inq.empty() + + def _run(self, mic): + mic_timeout = int(environ.get("MIC_TIMEOUT", 5)) + r = sr.Recognizer() + return r.listen( + mic, + timeout=mic_timeout, + phrase_time_limit=mic_timeout, + ) + +class Parser(threading.Thread): + def __init__(self, inq, outq): + threading.Thread.__init__(self) + self.inq = inq + self.outq = outq + + def run(self): + log("Parser.run: start") + while True: + try: + clip = self.inq.get() + if not clip: + break + self.outq.put(self._run(clip)) + except Exception as e: + log("Parser.run: error:", e) + self.outq.put(None) + log("Parser.run: stop") + + def _run(self, clip): + r = sr.Recognizer() + return r.recognize_whisper(clip, language="english") + +if __name__ == "__main__": + main()