def in_listening(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in listening state.""" if isinstance(message, MqttMessage): if message.topic == self.wake_topic: # Check site ID payload = json.loads(message.payload.decode()) payload_site_id = payload.get("siteId", "") if payload_site_id not in self.site_ids: self._logger.debug( "Got detected message, but wrong site id (%s)", payload_site_id ) return # Pass downstream to receivers self._logger.debug("Hotword detected (%s)", self.wakeword_id) result = WakeWordDetected(self.wakeword_id) for receiver in self.receivers: self.send(receiver, result) elif isinstance(message, StopListeningForWakeWord): if message.clear_all: self.receivers.clear() else: try: self.receivers.remove(message.receiver or sender) except ValueError: pass if len(self.receivers) == 0: self.transition("loaded") elif isinstance(message, PauseListeningForWakeWord): self.transition("paused")
def in_listening(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in listening state.""" if isinstance(message, AudioData): if not self.decoder_started: assert self.decoder is not None self.decoder.start_utt() self.decoder_started = True audio_data = message.data chunk = audio_data[:self.chunk_size] detected = False while chunk: result = self.process_data(chunk) if result is not None: detected = True self._logger.debug("Hotword detected (%s)", self.keyphrase) detected_msg = WakeWordDetected( self.keyphrase, audio_data_info=message.info) for receiver in self.receivers: self.send(receiver, detected_msg) break audio_data = audio_data[self.chunk_size:] chunk = audio_data[:self.chunk_size] # End utterance if detected and self.decoder_started: assert self.decoder is not None self.decoder.end_utt() self.decoder_started = False if not detected and self.not_detected: # Report non-detection not_detected_msg = WakeWordNotDetected( self.keyphrase, audio_data_info=message.info) for receiver in self.receivers: self.send(receiver, not_detected_msg) elif isinstance(message, StopListeningForWakeWord): if message.clear_all: self.receivers.clear() else: try: self.receivers.remove(message.receiver or sender) except ValueError: pass if not self.receivers: # End utterance if self.decoder_started: assert self.decoder is not None self.decoder.end_utt() self.decoder_started = False if message.record: self.send(self.recorder, StopStreaming(self.myAddress)) self.transition("loaded") elif isinstance(message, PauseListeningForWakeWord): self.transition("paused")
def in_listening(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in listening state.""" if isinstance(message, AudioData): audio_data = message.data chunk = audio_data[: self.chunk_size] detected = [] while chunk: for detector_index, result_index in enumerate(self.process_data(chunk)): if result_index > 0: detected.append(detector_index) if detected: # Don't process the rest of the audio data if hotword has # already been detected. break audio_data = audio_data[self.chunk_size :] chunk = audio_data[: self.chunk_size] # Handle results if detected: # Detected detected_names = [self.model_names[i] for i in detected] self._logger.debug("Hotword(s) detected: %s", detected_names) # Send events for model_name in detected_names: detected_event = WakeWordDetected( model_name, audio_data_info=message.info ) for receiver in self.receivers: self.send(receiver, detected_event) if self.single_detection: # Only allow for a single hotword to be detected break elif self.not_detected: # Not detected for model_name in self.model_names: not_detected_event = WakeWordNotDetected( model_name, audio_data_info=message.info ) for receiver in self.receivers: self.send(receiver, not_detected_event) elif isinstance(message, StopListeningForWakeWord): if message.clear_all: self.receivers.clear() else: try: self.receivers.remove(message.receiver or sender) except ValueError: pass if not self.receivers: if message.record: self.send(self.recorder, StopStreaming(self.myAddress)) self.transition("loaded") elif isinstance(message, PauseListeningForWakeWord): self.transition("paused")
def in_listening(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in listening state.""" if isinstance(message, AudioData): self.audio_buffer += message.data num_chunks = len(self.audio_buffer) // self.chunk_size if num_chunks > 0: assert self.handle is not None for _ in range(num_chunks): chunk = self.audio_buffer[: self.chunk_size] unpacked_chunk = struct.unpack_from(self.chunk_format, chunk) self.audio_buffer = self.audio_buffer[self.chunk_size :] # Process chunk keyword_index = self.handle.process(unpacked_chunk) if keyword_index: if len(self.keyword_paths) == 1: keyword_index = 0 wakeword_name = str(keyword_index) if keyword_index < len(self.keyword_paths): wakeword_name = self.keyword_paths[keyword_index].stem # Pass downstream to receivers self._logger.debug("Hotword detected (%s)", keyword_index) result = WakeWordDetected(wakeword_name) for receiver in self.receivers: self.send(receiver, result) elif isinstance(message, WakeWordDetected): # Pass downstream to receivers self._logger.debug("Hotword detected (%s)", message.name) for receiver in self.receivers: self.send(receiver, message) elif isinstance(message, WakeWordNotDetected): # Pass downstream to receivers for receiver in self.receivers: self.send(receiver, message) elif isinstance(message, StopListeningForWakeWord): if message.clear_all: self.receivers.clear() else: try: self.receivers.remove(message.receiver or sender) except ValueError: pass if not self.receivers: if message.record: self.send(self.recorder, StopStreaming(self.myAddress)) if self.handle is not None: self.handle.delete() self.handle = None self.transition("started") elif isinstance(message, PauseListeningForWakeWord): self.transition("paused")
def in_listening(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in listening state.""" try: if isinstance(message, AudioData): self.audio_info = message.info self.detected = False self.audio_buffer += message.data num_chunks = len(self.audio_buffer) // self.chunk_size if num_chunks > 0: assert self.stream is not None self.prediction_sem = threading.Semaphore() for _ in range(num_chunks): chunk = self.audio_buffer[: self.chunk_size] if chunk: self.stream.write(chunk) self.audio_buffer = self.audio_buffer[self.chunk_size :] if self.send_not_detected: # Wait for all chunks to finish processing for _ in range(num_chunks): self.prediction_sem.acquire(timeout=0.1) # Wait a little bit for the precise engine to finish processing time.sleep(self.chunk_delay) if not self.detected: # Not detected not_detected_event = WakeWordNotDetected( self.model_name, audio_data_info=message.info ) for receiver in self.receivers: self.send(receiver, not_detected_event) elif isinstance(message, StopListeningForWakeWord): if message.clear_all: self.receivers.clear() else: try: self.receivers.remove(message.receiver or sender) except ValueError: pass if not self.receivers: if message.record: self.send(self.recorder, StopStreaming(self.myAddress)) self.transition("loaded") elif isinstance(message, str): # Detected self._logger.debug("Hotword detected (%s)", self.model_name) detected_event = WakeWordDetected( self.model_name, audio_data_info=self.audio_info ) for receiver in self.receivers: self.send(receiver, detected_event) elif isinstance(message, PauseListeningForWakeWord): self.transition("paused") except Exception: self._logger.exception("in_listening")
def post_result() -> None: # STDOUT -> text try: out, _ = self.wake_proc.communicate() wakeword_id = out.decode().strip() except Exception: wakeword_id = "" self._logger.exception("post_result") # Actor will forward if len(wakeword_id) > 0: self.send(self.myAddress, WakeWordDetected(wakeword_id)) else: self.send(self.myAddress, WakeWordNotDetected(wakeword_id))