python - 如何将 MP3 音频文件读入 numpy 数组/将 numpy 数组保存到 MP3?

标签 python numpy audio ffmpeg mp3

有没有办法使用与 scipy.io.wavfile.readscipy.io.wavfile.write 类似的 API 将 MP3 音频文件读取到 numpy 数组中或从中写入 MP3 音频文件:

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?,但这并不能轻易涵盖多 channel 情况等。

最佳答案

按照许多有关读取 MP3 的文章中的建议,调用 ffmpeg 并手动解析其 stdout 是一项繁琐的任务(许多极端情况,因为可能有不同数量的 channel ,等等.),所以这是一个使用 pydub 的可行解决方案(您需要首先 pip install pydub)。

此代码允许使用与 scipy.io.wavfile.read/write 类似的 API 将 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")

注释:

  • 目前仅适用于 16 位文件(即使 24 位 WAV 文件很常见,但我很少见过 24 位 MP3 文件......这存在吗?)
  • normalized=True 允许使用 float 组([-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)

关于python - 如何将 MP3 音频文件读入 numpy 数组/将 numpy 数组保存到 MP3?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53633177/

相关文章:

python - NLP 句子意义提取方法

python - 带有数组的函数的 PyCharm getitem 警告

python - 如何在 python 中运行非线性回归

swift - 场景转换的声音,不会口吃

audio - 获取YouTube的所有媒体链接,而无需使用flashgot,youtube-dl或任何工具

python - 资源耗尽错误: OOM when allocating tensor

python - Django 如何定义权限以便用户只能编辑某些模型层次结构?

python - 如何高效地跟踪和更新大量的值?

python - python3.4 的 numpy 矩阵字符串

python - 如何使用python处理音频文件