Esempio n. 1
0
    def in_recording(self, message: Any, sender: RhasspyActor) -> None:
        """Handle messages in recording state."""
        if isinstance(message, AudioData):
            # Forward to subscribers
            for receiver in self.receivers:
                self.send(receiver, message)

            # Append to buffers
            for buffer_name in self.buffers:
                self.buffers[buffer_name] += message.data
        elif isinstance(message, StartStreaming):
            self.receivers.append(message.receiver or sender)
        elif isinstance(message, StartRecordingToBuffer):
            self.buffers[message.buffer_name] = bytes()
        elif isinstance(message, StopStreaming):
            if message.receiver is None:
                # Clear all receivers
                self.receivers.clear()
            else:
                self.receivers.remove(message.receiver)
        elif isinstance(message, StopRecordingToBuffer):
            if message.buffer_name is None:
                # Clear all buffers
                self.buffers.clear()
            else:
                # Respond with buffer
                buffer = self.buffers.pop(message.buffer_name, bytes())
                self.send(message.receiver or sender, AudioData(buffer))

        # Check to see if anyone is still listening
        if not self.receivers and not self.buffers:
            # Terminate audio recording
            self.is_recording = False
            self.transition("started")
            self._logger.debug("Stopped recording from microphone (stdin)")
Esempio n. 2
0
 def process_data(self):
     """Forward single audio chunk."""
     while True:
         data = sys.stdin.buffer.read(self.chunk_size)
         if self.is_recording and data:
             # Actor will forward
             self.send(self.myAddress, AudioData(data))
Esempio n. 3
0
            def gstreamer_thread_proc():
                try:
                    self._logger.debug(self.command)
                    self.gstreamer_proc = subprocess.Popen(
                        self.command, stdout=subprocess.PIPE
                    )

                    first_audio = True

                    while True:
                        chunk = self.gstreamer_proc.stdout.read(self.chunk_size)
                        if chunk:
                            if first_audio:
                                self._logger.debug("Receiving audio")
                                first_audio = False

                            message = AudioData(chunk)

                            # Forward to subscribers
                            for receiver in self.receivers:
                                self.send(receiver, message)

                            # Append to buffers
                            for buffer_name in self.buffers:
                                self.buffers[buffer_name] += message.data
                        else:
                            # Avoid 100% CPU
                            time.sleep(0.01)
                except Exception:
                    if self.gstreamer_proc is not None:
                        self._logger.exception(
                            "gstreamer_thread:Optional[threading.Thread]"
                        )
Esempio n. 4
0
    def in_recording(self, message: Any, sender: RhasspyActor) -> None:
        """Handle messages in recording state."""
        if isinstance(message, MqttMessage):
            if message.topic == self.topic_audio_frame:
                # Extract audio data
                with io.BytesIO(message.payload) as wav_buffer:
                    with wave.open(wav_buffer, mode="rb") as wav_file:
                        rate, width, channels = (
                            wav_file.getframerate(),
                            wav_file.getsampwidth(),
                            wav_file.getnchannels(),
                        )
                        if (rate != 16000) or (width != 2) or (channels != 1):
                            audio_data = convert_wav(message.payload)
                        else:
                            # Use original data
                            audio_data = wav_file.readframes(wav_file.getnframes())

                        data_message = AudioData(audio_data)

                # Forward to subscribers
                for receiver in self.receivers:
                    self.send(receiver, data_message)

                # Append to buffers
                for buffer_name in self.buffers:
                    self.buffers[buffer_name] += audio_data
        elif isinstance(message, StartStreaming):
            self.receivers.append(message.receiver or sender)
        elif isinstance(message, StartRecordingToBuffer):
            self.buffers[message.buffer_name] = bytes()
        elif isinstance(message, StopStreaming):
            if message.receiver is None:
                # Clear all receivers
                self.receivers.clear()
            else:
                self.receivers.remove(message.receiver)
        elif isinstance(message, StopRecordingToBuffer):
            if message.buffer_name is None:
                # Clear all buffers
                self.buffers.clear()
            else:
                # Respond with buffer
                buffer = self.buffers.pop(message.buffer_name, bytes())
                self.send(message.receiver or sender, AudioData(buffer))
Esempio n. 5
0
 def process_data() -> None:
     self.record_proc = subprocess.Popen(arecord_cmd, stdout=subprocess.PIPE)
     assert self.record_proc is not None
     while self.is_recording:
         # Pull from process STDOUT
         data = self.record_proc.stdout.read(self.chunk_size)
         if data:
             # Send to this actor to avoid threading issues
             self.send(self.myAddress, AudioData(data))
         else:
             # Avoid 100% CPU usage
             time.sleep(0.01)
Esempio n. 6
0
    def do_POST(self):
        """Handle POST requests."""
        try:
            self.recorder.get_response = None
            self.recorder.logger.debug("Receiving audio data")
            num_bytes = 0

            while True:
                # Assume chunked transfer encoding
                chunk_size_str = self.rfile.readline().decode().strip()
                if not chunk_size_str:
                    break

                chunk_size = int(chunk_size_str, 16)
                if chunk_size <= 0:
                    break

                audio_chunk = self.rfile.read(chunk_size)

                # Consume \r\n
                self.rfile.read(2)

                num_bytes += len(audio_chunk)
                message = AudioData(audio_chunk)

                # Forward to subscribers
                for receiver in self.recorder.receivers:
                    self.recorder.send(receiver, message)

                # Append to buffers
                for buffer_name in self.recorder.buffers:
                    self.recorder.buffers[buffer_name] += message.data

                if (self.recorder.stop_after != "never") and (
                    self.recorder.get_response is not None
                ):
                    # Stop
                    self.send_response(200)
                    self.end_headers()
                    return

            self.send_response(200)
            self.end_headers()
            self.wfile.write(str(num_bytes).encode())
        except Exception:
            self.recorder.logger.exception("do_POST")
Esempio n. 7
0
    def in_recording(self, message: Any, sender: RhasspyActor) -> None:
        """Handle messages in recording state."""
        if isinstance(message, StartStreaming):
            self.receivers.append(message.receiver or sender)
        elif isinstance(message, StartRecordingToBuffer):
            self.buffers[message.buffer_name] = bytes()
        elif isinstance(message, StopStreaming):
            if message.receiver is None:
                # Clear all receivers
                self.receivers.clear()
            else:
                self.receivers.remove(message.receiver)
        elif isinstance(message, StopRecordingToBuffer):
            if message.buffer_name is None:
                # Clear all buffers
                self.buffers.clear()
            else:
                # Respond with buffer
                buffer = self.buffers.pop(message.buffer_name, bytes())
                self.send(message.receiver or sender, AudioData(buffer))

        # Check to see if anyone is still listening
        if not self.receivers and not self.buffers:
            self.transition("started")
Esempio n. 8
0
 def in_started(self, message: Any, sender: RhasspyActor) -> None:
     """Handle messages in started state."""
     if isinstance(message, StopRecordingToBuffer):
         # Return empty buffer
         self._logger.warning("Dummy microphone system only returns empty buffers!")
         self.send(message.receiver or sender, AudioData(bytes()))
Esempio n. 9
0
            def stream_callback(data, frame_count, time_info, status):
                if data:
                    # Send to this actor to avoid threading issues
                    self.send(self.myAddress, AudioData(data))

                return (data, pyaudio.paContinue)