pyaudio stream.read() doesn't return data until stream stops

Viewed 593

I'll be very detailed so there is no lack of information about what is happening


I have a class named Stream, that has the main function of reading data output from any selected audio device connected to the PC and return the data to another class (this part is not implemented in the code yet, but it's just for context). Here is the Stream class:

Stream.py

import pyaudio
import struct

from threading import Thread

from LEDController.BaseClass import BaseClass
from LEDController.Device import Device


class Stream(BaseClass):
    def __init__(self, device: Device):
        super().__init__(__name__)
        self.__p = pyaudio.PyAudio()
        self.stream = None

        # Stream Settings
        self.defaultFrames = 1024 * 8
        self.format = pyaudio.paInt16
        self.channels = device.channels
        self.rate = device.defaultSampleRate
        self.input = True
        self.frames_per_buffer = self.defaultFrames
        self.input_device_index = device.index
        self.as_loopback = True

        self.__open()
        self.stop()

    def __open(self):
        try:
            self.logger.info('Trying to Open Stream')

            # Open Stream
            self.stream = self.__p.open(
                format=self.format,
                channels=self.channels,
                rate=self.rate,
                input=self.input,
                frames_per_buffer=self.defaultFrames,
                input_device_index=self.input_device_index,
                as_loopback=self.as_loopback,
                # wasapi_fill_silence=True
            )

        except Exception as e:
            self.logger.error(e)
        else:
            self.logger.info('Stream Opened')

    def start(self):
        try:
            self.stream.start_stream()

            self.read_thread = Thread(target=self.read)
            self.read_thread.start()

            self.logger.info("Stream Started")
            return True
        except Exception as e:
            return self.logger.error(e)

    def stop(self):
        try:
            self.stream.stop_stream()
            self.logger.info("Stream Stopped")

            return False
        except Exception as e:
            return self.logger.error(e)

    def is_stopped(self):
        return self.stream.is_stopped()

    def read(self):
        try:
            while not self.is_stopped():
                # Process Data
                data = self.stream.read(self.defaultFrames) # This line doesn't return anything
                data_int = struct.unpack(str(2 * self.defaultFrames) + 'h', data)
                print(data_int)
                # TODO return data

        except Exception as e:
            self.logger.error(e)

What it's doing:

At first, it receives a Device Object (code is not that important. However, I can edit and add it if needed). The Device object has a few pieces of information about the current selected device (such as device default sample rate, channels, etc, as you can see in Stream.__init__(). So the Stream class uses those pieces of information to open a PyAudio Stream with PyAudio.open(...) and right after that, it stops the stream until the user (there is a GUI) opens it.


The Problem

The Stream.read() method it's called by a Thread, so it keeps running, processing, and returning the data in real-time. However when I call Stream.start() and it starts the read method, the same keeps stuck in the following line:

data = self.stream.read(self.defaultFrames)

I've added a print statement in this method to see the data flowing. However, this statement only gets called after stopping the stream, and no error is shown.

Output

2020-06-03 09:15:21,718 — LEDController.Stream.Stream - 57 — INFO — Stream Started
2020-06-03 09:15:24,371 — LEDController.Stream.Stream - 65 — INFO — Stream Stopped
(output of the print statement, it's quite long so I'll not put it here)

As you can see, no data is printed while the stream is open. Looking at this output and after a few tests, I've figured out that self.stream.read(...) it's not returning any data, while the stream is opened and only returns when the stream stops. After that conclusion, I've started looking for solutions and doing more tests, but I couldn't find anything, and only for the recorded, this problem was not happening before (it started like yesterday) and I don't remember changing anything in my code.


Things that I've also tried, but haven't worked

  1. Removing the Thread and calling Stream.read() normally
  2. Reinstalling PyAudio

If you need any additional information, just tell me in the comments. I've tried to be as specific as possible and sorry if I didn't make my self clear enough. Just let me know and I'll update the question and fix the problem. Thanks in advance.

0 Answers
Related