9 import speech_recognition as sr
10 from pyutils import logging_utils
12 import kiosk_secrets as secrets
15 logger = logging.getLogger(__name__)
18 class HotwordListener(object):
24 input_device_index=None,
25 # library_path=pvporcupine.LIBRARY_PATH,
26 # model_path=pvporcupine.MODEL_PATH,
28 self._queue = command_queue
29 # self._library_path = library_path
30 # self._model_path = model_path
31 self._keyword_paths = keyword_paths
32 self._sensitivities = sensitivities
33 self._input_device_index = input_device_index
35 @logging_utils.LoggingContext(logger, prefix="listener:")
36 def listen_forever(self):
38 for x in self._keyword_paths:
39 keywords.append(os.path.basename(x).replace(".ppn", "").split("_")[0])
45 porcupine = pvporcupine.create(
46 keyword_paths=self._keyword_paths,
47 sensitivities=self._sensitivities,
48 access_key=secrets.pvporcupine_key,
50 recognizer = sr.Recognizer()
51 pa = pyaudio.PyAudio()
53 audio_stream = pa.open(
54 rate=porcupine.sample_rate,
56 format=pyaudio.paInt16,
58 frames_per_buffer=porcupine.frame_length,
59 input_device_index=self._input_device_index,
62 logger.info("Listening {")
63 for keyword, sensitivity in zip(keywords, self._sensitivities):
64 logger.info(" %s (%.2f)" % (keyword, sensitivity))
68 raw = audio_stream.read(
69 porcupine.frame_length, exception_on_overflow=False
71 pcm = struct.unpack_from("h" * porcupine.frame_length, raw)
72 result = porcupine.process(pcm)
74 cmd = "aplay /var/www/kiosk/attention.wav"
76 "Running %s (attention tone) because I heard the wake-word", cmd
80 ">>>>>>>>>>>>> Detected wakeword %s" % keywords[result]
84 0, int(porcupine.sample_rate / porcupine.frame_length * 4)
86 raw += audio_stream.read(
87 porcupine.frame_length, exception_on_overflow=False
90 f">>>>>>>>>>>>>> Recognizing command... {len(raw)} bytes"
92 speech = sr.AudioData(
93 frame_data=bytes(raw),
94 sample_rate=porcupine.sample_rate,
95 sample_width=2, # 16 bits
97 command = recognizer.recognize_google(speech)
98 logger.debug(">>>>>>>>>>>>> Google says command was %s" % command)
99 logger.info("Enqueued command=%s", command)
100 self._queue.put(command)
103 logger.exception("Stopping listener because of unexpected exception!")
105 except KeyboardInterrupt:
106 logger.exception("Stopping listener because of ^C!")
109 logger.debug("Cleaning up... one sec...")
110 if porcupine is not None:
113 if audio_stream is not None:
120 def show_audio_devices(cls):
121 fields = ("index", "name", "defaultSampleRate", "maxInputChannels")
122 pa = pyaudio.PyAudio()
123 for i in range(pa.get_device_count()):
124 info = pa.get_device_info_by_index(i)
125 print(", ".join("'%s': '%s'" % (k, str(info[k])) for k in fields))
130 keyword_paths = [pvporcupine.KEYWORD_PATHS[x] for x in ["blueberry", "bumblebee"]]
131 sensitivities = [0.85, 0.95]
139 if __name__ == "__main__":