如何在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字节流的主要内容,如果未能解决你的问题,请参考以下文章