Bas*_*asj 6 python audio mp3 ffmpeg numpy
有没有一种方法可以numpy使用与scipy.io.wavfile.read和scipy.io.wavfile.write相似的API,将MP3音频文件读入数组/从数组写入MP3音频文件:
sr, x = wavfile.read('test.wav')
wavfile.write('test2.wav', sr, x)
Run Code Online (Sandbox Code Playgroud)
?
注意:pydub的AudioSegment对象不能直接访问numpy数组。
PS:我已经阅读了将声音文件作为NumPy数组(到audiolab的替代品)导入Python的方法,尝试了所有答案,包括那些需要Popenffmpeg并从stdout管道读取内容的答案,等等。我也已经阅读了尝试转换mp3文件到Numpy Array,然后ffmpeg挂起,等等,并尝试了主要答案,但是没有简单的解决方案。在花了几个小时之后,我在这里将其发布为“回答您自己的问题-以Q&A方式分享您的知识”。我还阅读了如何从pydub AudioSegment创建numpy数组?但这并不能轻易涵盖多通道情况等。
Bas*_*asj 15
正如许多关于阅读MP3的文章中所建议的那样,调用ffmpeg并手动解析它stdout是一项繁琐的任务(在许多特殊情况下,因为可能会使用不同数量的通道,等等),因此这是一个使用pydub(您需要pip install pydub首先使用)的可行解决方案。
此代码允许使用类似于以下内容的APIscipy.io.wavfile.read/write读取MP3到numpy数组/将numpy数组写入MP3文件:
import pydub
import numpy as np
def read(f, normalized=False):
"""MP3 to numpy array"""
a = pydub.AudioSegment.from_mp3(f)
y = np.array(a.get_array_of_samples())
if a.channels == 2:
y = y.reshape((-1, 2))
if normalized:
return a.frame_rate, np.float32(y) / 2**15
else:
return a.frame_rate, y
def write(f, sr, x, normalized=False):
"""numpy array to MP3"""
channels = 2 if (x.ndim == 2 and x.shape[1] == 2) else 1
if normalized: # normalized array - each item should be a float in [-1, 1)
y = np.int16(x * 2 ** 15)
else:
y = np.int16(x)
song = pydub.AudioSegment(y.tobytes(), frame_rate=sr, sample_width=2, channels=channels)
song.export(f, format="mp3", bitrate="320k")
Run Code Online (Sandbox Code Playgroud)
笔记:
normalized=True 允许使用浮点数组([-1,1中的每个项目)用法示例:
sr, x = read('test.mp3')
print(x)
#[[-225 707]
# [-234 782]
# [-205 755]
# ...,
# [ 303 89]
# [ 337 69]
# [ 274 89]]
write('out2.mp3', sr, x)
Run Code Online (Sandbox Code Playgroud)
您可以使用audio2numpy库。安装与
pip install audio2numpy
Run Code Online (Sandbox Code Playgroud)
那么,你的代码将是:
pip install audio2numpy
Run Code Online (Sandbox Code Playgroud)
对于写作,请使用@Basj的答案