9 import speech_recognition as sr
10 from pyutils import logging_utils
12 import kiosk_secrets as secrets
14 logger = logging.getLogger(__name__)
17 class HotwordListener(object):
23 input_device_index=None,
24 # library_path=pvporcupine.LIBRARY_PATH,
25 # model_path=pvporcupine.MODEL_PATH,
27 self._queue = command_queue
28 # self._library_path = library_path
29 # self._model_path = model_path
30 self._keyword_paths = keyword_paths
31 self._sensitivities = sensitivities
32 self._input_device_index = input_device_index
34 @logging_utils.LoggingContext(logger, prefix="listener:")
35 def listen_forever(self):
37 for x in self._keyword_paths:
38 keywords.append(os.path.basename(x).replace(".ppn", "").split("_")[0])
44 porcupine = pvporcupine.create(
45 keyword_paths=self._keyword_paths,
46 sensitivities=self._sensitivities,
47 access_key=secrets.pvporcupine_key,
49 recognizer = sr.Recognizer()
50 pa = pyaudio.PyAudio()
52 audio_stream = pa.open(
53 rate=porcupine.sample_rate,
55 format=pyaudio.paInt16,
57 frames_per_buffer=porcupine.frame_length,
58 input_device_index=self._input_device_index,
61 logger.info("Listening {")
62 for keyword, sensitivity in zip(keywords, self._sensitivities):
63 logger.info(" %s (%.2f)" % (keyword, sensitivity))
67 raw = audio_stream.read(
68 porcupine.frame_length, exception_on_overflow=False
70 pcm = struct.unpack_from("h" * porcupine.frame_length, raw)
71 result = porcupine.process(pcm)
73 cmd = "aplay /var/www/kiosk/attention.wav"
75 "Running %s (attention tone) because I heard the wake-word", cmd
79 ">>>>>>>>>>>>> Detected wakeword %s" % keywords[result]
83 0, int(porcupine.sample_rate / porcupine.frame_length * 4)
85 raw += audio_stream.read(
86 porcupine.frame_length, exception_on_overflow=False
89 f">>>>>>>>>>>>>> Recognizing command... {len(raw)} bytes"
91 speech = sr.AudioData(
92 frame_data=bytes(raw),
93 sample_rate=porcupine.sample_rate,
94 sample_width=2, # 16 bits
96 command = recognizer.recognize_google(speech)
97 logger.debug(">>>>>>>>>>>>> Google says command was %s" % command)
98 logger.info("Enqueued command=%s", command)
99 self._queue.put(command)
102 logger.exception("Stopping listener because of unexpected exception!")
104 except KeyboardInterrupt:
105 logger.exception("Stopping listener because of ^C!")
108 logger.debug("Cleaning up... one sec...")
109 if porcupine is not None:
112 if audio_stream is not None:
119 def show_audio_devices(cls):
120 fields = ("index", "name", "defaultSampleRate", "maxInputChannels")
121 pa = pyaudio.PyAudio()
122 for i in range(pa.get_device_count()):
123 info = pa.get_device_info_by_index(i)
124 print(", ".join("'%s': '%s'" % (k, str(info[k])) for k in fields))
129 keyword_paths = [pvporcupine.KEYWORD_PATHS[x] for x in ["blueberry", "bumblebee"]]
130 sensitivities = [0.85, 0.95]
138 if __name__ == "__main__":