无需在 Python 中写入磁盘即可加入 .wav 文件

Posted

技术标签:

【中文标题】无需在 Python 中写入磁盘即可加入 .wav 文件【英文标题】:Joining .wav files without writing on disk in Python 【发布时间】:2018-05-24 19:58:50 【问题描述】:

我有一个二进制格式的 .wav 文件列表(它们来自 websocket),我想加入一个二进制 .wav 文件,然后用它进行语音识别。我已经能够使用以下代码使其工作:

audio = [binary_wav1, binary_wav2,..., binary_wavN] # a list of .wav binary files coming from a socket
audio = [io.BytesIO(x) for x in audio]

# Join wav files
with wave.open('/tmp/input.wav', 'wb') as temp_input:
    params_set = False
    for audio_file in audio:
        with wave.open(audio_file, 'rb') as w:
            if not params_set:
                temp_input.setparams(w.getparams())
                params_set = True
            temp_input.writeframes(w.readframes(w.getnframes()))

# Do speech recognition
binary_audio = open('/tmp/input.wav', 'rb').read())
ASR(binary_audio)

问题是我不想将文件'/tmp/input.wav' 写入磁盘。有什么办法可以做到不写任何文件到磁盘?

谢谢。

【问题讨论】:

单声道时声音可以表示为一维数组,立体声时可以表示为二维。使用 wavefile 之类的东西来获取原始数据。 wave.open 接受文件路径或类似文件的对象。您已经导入了BytesIO,所以只需将其中一个用作缓冲区之类的文件。 Here's 和某人使用 gzip 的示例(注意参数名称略有不同)。 【参考方案1】:

拥有一个文件但从不将其放入磁盘的一般解决方案是流。为此,我们使用io 库,这是处理内存流的默认库。你甚至已经在你的代码前面使用了BytesIO

audio = [binary_wav1, binary_wav2,..., binary_wavN] # a list of .wav binary files coming from a socket
audio = [io.BytesIO(x) for x in audio]

# Join wav files

params_set = False
temp_file = io.BytesIO()
with wave.open(temp_file, 'wb') as temp_input:
    for audio_file in audio:
        with wave.open(audio_file, 'rb') as w:
            if not params_set:
                temp_input.setparams(w.getparams())
                params_set = True
            temp_input.writeframes(w.readframes(w.getnframes()))

#move the cursor back to the beginning of the "file"
temp_file.seek(0)
# Do speech recognition
binary_audio = temp_file.read()
ASR(binary_audio)

注意我没有任何 .wav 文件可供试用。由wave 库来正确处理真实文件和缓冲流之间的差异。

【讨论】:

谢谢,这行得通!我之前尝试过,但我错过了temp_file.seek(0) 语句,所以我当时只是在读取一个空的二进制对象。【参考方案2】:

使用 scipy 和 numpy,您可以将 wav 文件读取为 numpy 数组,然后进行您想要的修改。

from scipy.io import wavfile
import numpy as np

# load files
_, arr1 = wavfile.read('song.wav')
_, arr2 = wavfile.read('Aaron_Copland-Quiet_City.wav')

print(arr1.shape)
print(arr2.shape)

>>> (1323001,)
>>> (1323000,)

# make new array by concatenating two audio waves
new_arr = np.hstack((arr1, arr2))
print(new_arr.shape)

>>> (2646001,)

# save new audio wave
wavfile.write('new_audio.wav')

【讨论】:

这行得通,但是添加对 scipy 和/或 numpy 的依赖似乎有点过头了。正如@Aaron 在他的回答中指出的那样,您可以简单地写入类似文件的对象,例如BytesIO

以上是关于无需在 Python 中写入磁盘即可加入 .wav 文件的主要内容,如果未能解决你的问题,请参考以下文章

构造一个 wav 文件并使用 scipy 将其写入磁盘

如何使用 C# NAudio 操作字节?

创建并使用 WAV 文件作为对象 Python

如何在 Javascript/Node 中从 blob 写入 .wav 文件

如何使用 python 连接两个 wav 文件?

Python:将 wav 文件写入 numpy 浮点数组