使用一个 pyaudio 流进行数据读写

Using one pyaudio stream for both data reading and writing

我有一个网络套接字客户端,它在请求中发送音频二进制数据,并从网络套接字服务器接收它们作为响应。我正在使用 pyaudio 从 (file/microphone) 读取二进制音频数据,然后将其发送到服务器。然后作为响应,我从服务器接收到另一个二进制音频数据。问题是我可以使用我最近打开的 pyaudio 阅读流来实时播放接收音频,还是我最好需要创建另一个 pyaudio 流(有两个流,一个负责二进制数据读取,另一个负责二进制数据写入)?

请注意,据我所知,读取流数据是一种生成器进程。一旦你读了它,你就丢失了数据——换句话说:基于你的块,你基本上每 'read' 移动一个指针来获取你的二进制数据。

回答

为什么不创建 2 个线程和 2 个流?不要害怕流。您可以根据需要初始化任意多个。

  • 1 个线程接收二进制数据并将它们推入流(从客户端到您的声音设备)
  • 2 线程从您的输入流接收数据(从您的麦克风以二进制形式)并将它们推送给您的客户端?

我现在正在使用 PyAudio 进行一些工作,流式传输非常有趣,但从编程的角度来看很难理解。实际上,您可以在耳机中创建 2 个输出流,并在到达耳机的途中在硬件中的某个地方将流汇总起来,这样您就可以同时收听两种声音。

注意:

我还想说您不必担心使用线程。这些流是批量工作的,而不是实时的。无论是读取还是写入,它的工作方式都是将二进制数据推送到流中,然后就完成了。硬件接受二进制数据,将它们流式传输,只有在它完成后,流才会请求另一个数据。所以如果你有 sample_rate 44100 和块 22050(只是例子),你的循环将只有 0.5s。因此,您甚至不必担心溢出、要处理的数据太多或您的线程变得疯狂。 事实上,当您将数据推送到流时,您的 python 就在等待您的硬件完成这项工作。它非常轻便。

没有理由创建两个流。 在同一个流回调函数中读写是完全没问题的。 只需在 "non-blocking" 模式下创建流(即通过指定回调函数)。

您只需确保使用足够大的缓冲区,以防网络连接在某个时间点花费的时间比平均时间长一些。 您应该使用某种队列在线程之间移动数据,例如queue.Queue 来自 Python 的标准库。

也没有必要创建单独的线程。如果您使用带有回调函数的 PyAudio 流,该函数会在单独的线程中自动调用(由底层 PortAudio 库自动创建)。

话虽如此,如果出于某些其他原因需要它们,您当然可以 创建多个流。此外,如果需要,您可以创建线程。