예제 #1
0
    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")
예제 #2
0
    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")
예제 #3
0
파일: wake.py 프로젝트: swipswaps/rhasspy
    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")
예제 #4
0
파일: wake.py 프로젝트: swipswaps/rhasspy
    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")
예제 #5
0
파일: wake.py 프로젝트: swipswaps/rhasspy
    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")
예제 #6
0
            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))