如何在python中读取.wav字节流

Posted

技术标签:

【中文标题】如何在python中读取.wav字节流【英文标题】:How to read stream of .wav bytes in python 【发布时间】:2017-10-09 12:57:47 【问题描述】:

有没有办法读取 .wav 格式的二进制数据帧?我正在将 .wav 二进制流式传输到 python 服务器,我希望能够从 pyaudio 的处理中读取和使用它,它抱怨帧大小。

由于我无法使用wave.open('filename.wav'),因为我已经有二进制数据正在流式传输,有没有办法读取二进制数据以便我可以使用wave python 库中的readframes 方法?

编辑: 我尝试从客户端流式传输readframes,但是 pyaudio 给出了一个错误,即字节不是 .wav 格式。但是,如果我可以在服务器上完成这将是理想的。

【问题讨论】:

您的意思是getnframes 还是readframes?我在文档中没有看到getframes readframes,很抱歉造成混乱。我尝试从客户端流式传输读取帧,但是 pyaudio 给出了一个错误,即字节不是 .wav 格式。但是,如果我可以在服务器端完成这将是理想的。 您可以使用wave 所需的所有file 方法创建一个对象,并将其传递给wave.open:“如果文件是字符串,则使用该名称打开文件,否则将其视为可查找的类似文件的对象。” 你的二进制流中有什么?它是 WAV 文件的全部内容,包括标题,还是只是纯音频样本?如果是后者,您可以直接将字节传递给 PyAudio,您只需确保传递正确数量的数据,并告诉 PyAudio 正确的数据类型和通道数。顺便说一句,PyAudio 不知道 WAV 文件,我很确定它不会在错误消息中谈论它们。您应该提供实际的错误消息! 【参考方案1】:
from scipy.io import wavfile
fs, data = wavfile.read('your file path')

【讨论】:

【参考方案2】:

正如@Vishesh Mangla 指出的那样,使用 librosa 是一个很棒的音频信号库

import librosa

sr = librosa.get_samplerate('/path/to/file.wav')

# Set the frame parameters to be equivalent to the librosa defaults
# in the file's native sampling rate
frame_length = (2048 * sr) // 22050
hop_length = (512 * sr) // 22050

# Stream the data, working on 128 frames at a time
stream = librosa.stream('path/to/file.wav',
                        block_length=128,
                        frame_length=frame_length,
                        hop_length=hop_length)

chromas = []
for y in stream:
   chroma_block = librosa.feature.chroma_stft(y=y, sr=sr,
                                              n_fft=frame_length,
                                              hop_length=hop_length,
                                              center=False)
   chromas.append(chromas)

在此示例中,每个音频片段 y 将包含 128 帧的样本,或者更具体地说,len(y) == frame_length + (block_length - 1) * hop_length。每个片段 y 将与后续片段重叠 frame_length - hop_length 样本,这确保流处理将提供与一步处理整个序列相同的结果(假设填充/居中已禁用)。

更多关于流接口的详细信息,请参考librosa.core.stream。

【讨论】:

【参考方案3】:

回答我自己的赏金,有一个优雅的解决方案,我borrow from this more general context relating to getting a virtual file object。

import io
audio = wave.open(io.BytesIO(bytes))

这将为 python 字节对象启用所有 wave 的 API,至少是我用于与原始问题相同的场景的子集。例如,使用上面的 audio 变量,您现在可以:

format=self.audio.get_format_from_width(
   audio.getsampwidth()),
   channels=audio.getnchannels(),
   rate=audio.getframerate(),
   frames_per_buffer=self.chunk_size,
   output=True)

因为看起来 wave 库除了磁盘文件对象之外不直接支持任何东西,这是一个很好的解决方法,至少它取决于标准 python 库 (io),它提供了我们需要的东西来弥合API。

【讨论】:

以上是关于如何在python中读取.wav字节流的主要内容,如果未能解决你的问题,请参考以下文章

从“无符号”字节流中读取 32 位有符号值

JAVA读取字节流

java读取文件问题该选字节流还是字符流?

字节流和字符流

字节流字符流中

流概述与字节流输入输出