【问题标题】:How to read a MP3 audio file into a numpy array / save a numpy array to MP3?如何将 MP3 音频文件读入 numpy 数组/将 numpy 数组保存到 MP3?
【发布时间】:2019-05-07 01:46:51
【问题描述】:

有没有办法通过与scipy.io.wavfile.readscipy.io.wavfile.write 类似的API 将MP3 音频文件读入/写出numpy 数组:

sr, x = wavfile.read('test.wav')
wavfile.write('test2.wav', sr, x)

?

注意:pydubAudioSegment 对象不能直接访问 numpy 数组。

PS:我已经阅读了Importing sound files into Python as NumPy arrays (alternatives to audiolab),尝试了所有答案,包括那些需要Popen ffmpeg 并从stdout 管道中读取内容等的答案。我还阅读了Trying to convert an mp3 file to a Numpy Array, and ffmpeg just hangs 等。 ,并尝试了主要答案,但没有简单的解决方案。在花了几个小时之后,我将其发布在此处,并附有“回答你自己的问题——分享你的知识,问答式”。我也读过How to create a numpy array from a pydub AudioSegment?,但这并不容易涵盖多通道情况等。

【问题讨论】:

    标签: python numpy audio ffmpeg mp3


    【解决方案1】:

    调用ffmpeg 并手动解析其stdout,正如许多关于阅读MP3 的帖子中所建议的那样是一项乏味的任务(许多极端情况,因为可能有不同数量的通道等),所以这是一个使用的工作解决方案pydub(你需要先pip install pydub)。

    此代码允许将 MP3 读取到 numpy 数组/将 numpy 数组写入 MP3 文件使用与 scipy.io.wavfile.read/write 类似的 API

    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")
    

    注意事项:

    • 目前仅适用于 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)
    

    【讨论】:

    • 太棒了!对于 linux 用户,可以将输出/参数 tags 添加到读/写以检索和保存元数据,如 github.com/jiaaro/pydub/issues/44 所示。添加tags=mediainfo(f).get('TAG', {}) 读取和export(f, format="mp3", bitrate="320k", tags=tags) 写入。
    • 为了使用此解决方案,可能需要一些额外的依赖项(不能仅在 Windows 上使用 pip 安装)。见github.com/jiaaro/pydub/issues/348
    【解决方案2】:

    您可以使用 audio2numpy 库。 安装

    pip install audio2numpy
    

    那么,您的代码将是:

    import audio2numpy as a2n
    x,sr=a2n.audio_from_file("test.mp3")
    

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

    【讨论】:

    • 这些多合一的软件包在快速实施实验时非常有用,但在我看来,使用它们甚至比复制粘贴像@Basj 的答案更糟糕。 (无论如何+1)
    • 是的...但是它可以工作,如果您不关心代码的速度或效率,这是最简单的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 2018-03-25
    • 2016-06-21
    • 2018-12-15
    相关资源
    最近更新 更多