Pyaudio Stream Crashing on Raspberry Pi4

46 Views Asked by At

I am running a pyaudio stream as part of a voice assistant application I am writing. The pyaudio stream is continuous and writes data to a buffer that other components in the app can read from to detect things like a wake word, and so on. These other components are on a separate thread when they read from the buffer, they do not modify the buffer at all. Im running into a situation when running it on a raspberry pi4 where it works initially, it can detect the wake word and record my command. But when the second wake word is detected it crashes. On windows and mac this does not occur.

This is the code that runs the pyaudio stream

import queue
import pyaudio
import time

class Stream():
    def __init__(self, 
                 node,
                 frames_per_buffer: int = 1024,
                 recording_buffer_size: int = 12
    ):
        self.mic_idx = node.mic_idx
        self.sample_rate = node.sample_rate
        self.sample_width = node.sample_width
        self.channels = node.audio_channels
        self.frames_per_buffer = frames_per_buffer

        # Define a buffer to store audio frames
        self.buffer = queue.Queue()

    def start(self):
        self.record()

    def record(self):
        pass

    def get_chunk(self) -> bytes:
        return self.buffer.get()

    def clear(self):
        self.buffer.queue.clear()

class PyaudioStream(Stream):

    def record(self):
        try:
            audio = pyaudio.PyAudio()

            def callback(in_data, frame_count, time_info, status):
                if in_data:
                    self.buffer.put(in_data)

                return (None, pyaudio.paContinue)

            # Open device
            mic = audio.open(
                input_device_index=self.mic_idx,
                channels=self.channels,
                format=audio.get_format_from_width(self.sample_width),
                rate=self.sample_rate,
                frames_per_buffer=self.frames_per_buffer,
                input=True,
                stream_callback=callback
            )

            assert mic is not None
            mic.start_stream()
            print("Pyaudio stream started")

            while mic.is_active():
                time.sleep(0.1)

            print("Finished recording")
            mic.stop_stream()
            audio.terminate()

        except Exception as e:
            print(repr(e))
            print("Error recording")
            raise e

This is the error itself

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/pi/openvoiceassistant-node/node/__main__.py", line 78, in <module>
    run_node()
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pi/openvoiceassistant-node/node/__main__.py", line 75, in run_node
    node.start()
  File "/home/pi/openvoiceassistant-node/node/node.py", line 33, in start
    self.stream.start()
  File "/home/pi/openvoiceassistant-node/node/stream.py", line 21, in start
    self.record()
  File "/home/pi/openvoiceassistant-node/node/stream.py", line 69, in record
    raise e
  File "/home/pi/openvoiceassistant-node/node/stream.py", line 59, in record
    while mic.is_active():
          ^^^^^^^^^^^^^^^
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/pyaudio.py", line 538, in is_active
    return pa.is_stream_active(self._stream)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno -10000] PortAudio not initialized
Exception ignored in atexit callback: <function _exit_handler at 0xf6ae7b68>
Traceback (most recent call last):
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/sounddevice.py", line 2874, in _exit_handler
    _terminate()
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/sounddevice.py", line 2858, in _terminate
    _check(_lib.Pa_Terminate(), 'Error terminating PortAudio')
  File "/home/pi/openvoiceassistant-node/env/node/lib/python3.11/site-packages/sounddevice.py", line 2747, in _check
    raise PortAudioError(errormsg, err)

The error seems to be coming from the mic.is_active() function

I cant find any resources specifically related to this error. I was curious if it had anything to do with this environment variable I set specifically on the raspberry pi export PA_ALSA_PLUGHW=1

I cant imagine it has anything to do with the code that reads from the stream, since it does not seem to be related to an issue with the buffer.

I've tried putting the pyaudio stream on the main thread but that didnt fix the issue.

0

There are 0 best solutions below