async def handle_detection( self, matching_indexes: typing.List[int], raven: Raven ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordDetected, TopicArgs], HotwordError]]: """Handle a successful hotword detection""" try: template = raven.templates[matching_indexes[0]] wakeword_id = raven.keyword_name or template.name if not wakeword_id: wakeword_id = "default" yield ( HotwordDetected( site_id=self.last_audio_site_id, model_id=template.name, current_sensitivity=raven.probability_threshold, model_version="", model_type="personal", lang=self.lang, ), { "wakeword_id": wakeword_id }, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError( error=str(e), context=f"{raven.keyword_name}: {template.name}", site_id=self.last_audio_site_id, )
async def handle_detection( self, wakeword_id: str, site_id: str = "default" ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordDetected, TopicArgs], HotwordError]]: """Handle a successful hotword detection""" try: yield ( HotwordDetected( site_id=site_id, model_id=self.keyphrase, current_sensitivity=self.keyphrase_threshold, model_version="", model_type="personal", ), { "wakeword_id": wakeword_id }, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError(error=str(e), context=self.keyphrase, site_id=site_id)
async def handle_detection( self, keyword_index: int, wakeword_id: str, site_id="default" ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordDetected, TopicArgs], HotwordError]]: """Handle a successful hotword detection""" try: assert (len(self.model_ids) > keyword_index), f"Missing {keyword_index} in models" yield ( HotwordDetected( site_id=site_id, model_id=self.model_ids[keyword_index], current_sensitivity=self.sensitivities[keyword_index], model_version="", model_type="personal", lang=self.lang, ), { "wakeword_id": wakeword_id }, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError(error=str(e), context=str(keyword_index), site_id=site_id)
async def handle_get_hotwords( self, get_hotwords: GetHotwords ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]: """Report available hotwords""" try: models: typing.List[Hotword] = [] # Each keyword is in a separate Raven instance for raven in self.ravens: # Assume that the directory name is something like # "okay-rhasspy" for the keyword "okay rhasspy". models.append( Hotword( model_id=raven.keyword_name, model_words=re.sub(r"[_-]+", " ", raven.keyword_name), )) yield Hotwords(models=models, id=get_hotwords.id, site_id=get_hotwords.site_id) except Exception as e: _LOGGER.exception("handle_get_hotwords") yield HotwordError(error=str(e), context=str(get_hotwords), site_id=get_hotwords.site_id)
async def handle_detection( self, ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordDetected, TopicArgs], HotwordError]]: """Handle a successful hotword detection""" try: wakeword_id = self.wakeword_id if not wakeword_id: # Use file name wakeword_id = self.model_path.stem yield ( HotwordDetected( site_id=self.last_audio_site_id, model_id=self.model_id, current_sensitivity=self.sensitivity, model_version="", model_type="personal", ), { "wakeword_id": wakeword_id }, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError( error=str(e), context=str(self.model_path), site_id=self.last_audio_site_id, )
async def handle_detection( self, model_index: int, wakeword_id: str, site_info: SiteInfo ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordDetected, TopicArgs], HotwordError]]: """Handle a successful hotword detection""" try: assert (len(site_info.model_ids) > model_index), f"Missing {model_index} in models" sensitivity = 0.5 if model_index < len(self.models): sensitivity = self.models[model_index].float_sensitivity() yield ( HotwordDetected( site_id=site_info.site_id, model_id=site_info.model_ids[model_index], current_sensitivity=sensitivity, model_version="", model_type="personal", lang=self.lang, ), { "wakeword_id": wakeword_id }, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError(error=str(e), context=str(model_index), site_id=site_info.site_id)
async def handle_detection( self, matching_indexes: typing.List[int] ) -> typing.AsyncIterable[ typing.Union[typing.Tuple[HotwordDetected, TopicArgs], HotwordError] ]: """Handle a successful hotword detection""" try: template = self.raven.templates[matching_indexes[0]] wakeword_id = self.wakeword_id if not wakeword_id: wakeword_id = template.name yield ( HotwordDetected( site_id=self.last_audio_site_id, model_id=template.name, current_sensitivity=self.raven.distance_threshold, model_version="", model_type="personal", ), {"wakeword_id": wakeword_id}, ) except Exception as e: _LOGGER.exception("handle_detection") yield HotwordError( error=str(e), context=str(matching_indexes), site_id=self.last_audio_site_id, )
async def handle_get_hotwords( self, get_hotwords: GetHotwords ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]: """Report available hotwords""" try: yield Hotwords(models=[], id=get_hotwords.id, site_id=get_hotwords.site_id) except Exception as e: _LOGGER.exception("handle_get_hotwords") yield HotwordError( error=str(e), context=str(get_hotwords), site_id=get_hotwords.site_id )
async def handle_get_hotwords( self, get_hotwords: GetHotwords ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]: """Report available hotwords""" try: if self.model_dirs: # Add all models from model dirs model_paths = [] for model_dir in self.model_dirs: if not model_dir.is_dir(): _LOGGER.warning("Model directory missing: %s", str(model_dir)) continue for model_file in model_dir.iterdir(): if model_file.is_file() and (model_file.suffix in [".umdl", ".pmdl"]): model_paths.append(model_file) else: # Add current model(s) only model_paths = [Path(model.model_path) for model in self.models] hotword_models: typing.List[Hotword] = [] for model_path in model_paths: model_words = " ".join( model_path.with_suffix("").name.split("_")) model_type = "universal" if model_path.suffix == ".umdl" else "personal" hotword_models.append( Hotword( model_id=model_path.name, model_words=model_words, model_type=model_type, )) yield Hotwords(models=hotword_models, id=get_hotwords.id, site_id=get_hotwords.site_id) except Exception as e: _LOGGER.exception("handle_get_hotwords") yield HotwordError(error=str(e), context=str(get_hotwords), site_id=get_hotwords.site_id)
async def handle_record_example( self, record_example: RecordHotwordExample ) -> typing.AsyncIterable[typing.Union[typing.Tuple[ HotwordExampleRecorded, TopicArgs], HotwordError]]: """Record an example of a hotword.""" try: if self.recording_example: _LOGGER.warning("Cancelling previous recording") self.example_recorder.stop() # Start recording assert self.loop, "No loop" self.example_future = self.loop.create_future() self.example_recorder.start() self.recording_example = True # Wait for result _LOGGER.debug("Recording example (id=%s)", record_example.id) example_audio = await self.example_future assert isinstance(example_audio, bytes) # Trim silence _LOGGER.debug("Trimming silence from example") example_audio = trim_silence(example_audio) # Convert to WAV format wav_data = self.to_wav_bytes(example_audio) yield ( HotwordExampleRecorded(wav_bytes=wav_data), { "site_id": record_example.site_id, "request_id": record_example.id }, ) except Exception as e: _LOGGER.exception("handle_record_example") yield HotwordError( error=str(e), context=str(record_example), site_id=record_example.site_id, )
async def handle_get_hotwords( self, get_hotwords: GetHotwords ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]: """Report available hotwords""" try: if self.keyword_dirs: # Add all models from keyword dir model_paths = [] for keyword_dir in self.keyword_dirs: if not keyword_dir.is_dir(): _LOGGER.warning("Missing keyword dir: %s", str(keyword_dir)) continue for keyword_file in keyword_dir.glob("*.ppn"): model_paths.append(keyword_file) else: # Add current model(s) only model_paths = [Path(model_id) for model_id in self.model_ids] models: typing.List[Hotword] = [] for ppn_file in model_paths: words = ppn_file.with_suffix("").name.split("_") if len(words) == 1: # porcupine.ppn -> "porcupine" model_words = words[0] else: # smart_mirror_linux.ppn -> "smart mirror" model_words = " ".join(words[:-1]) models.append( Hotword(model_id=ppn_file.name, model_words=model_words)) yield Hotwords(models=models, id=get_hotwords.id, site_id=get_hotwords.site_id) except Exception as e: _LOGGER.exception("handle_get_hotwords") yield HotwordError(error=str(e), context=str(get_hotwords), site_id=get_hotwords.site_id)