如何将MP3音频文件读取到numpy数组中/如何将numpy数组保存到MP3?

Bas*_*asj 6 python audio mp3 ffmpeg numpy

有没有一种方法可以numpy使用与scipy.io.wavfile.readscipy.io.wavfile.write相似的API,将MP3音频文件读入数组/从数组写入MP3音频文件:

sr, x = wavfile.read('test.wav')
wavfile.write('test2.wav', sr, x)
Run Code Online (Sandbox Code Playgroud)

注意:pydubAudioSegment对象不能直接访问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)

笔记:

  • 目前仅适用于16位文件(即使24位WAV文件非常普遍,我也很少见过24位MP3文件...是否存在?)
  • 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)


Ada*_*nča 6

您可以使用audio2numpy库。安装与

pip install audio2numpy
Run Code Online (Sandbox Code Playgroud)

那么,你的代码将是:

pip install audio2numpy
Run Code Online (Sandbox Code Playgroud)

对于写作,请使用@Basj的答案