【问题标题】:How can I convert a .wav to .mp3 in-memory?如何在内存中将 .wav 转换为 .mp3?
【发布时间】:2021-08-26 07:15:50
【问题描述】:

我有一个来自 some.npy 文件的 numpy 数组,其中包含以 .wav 格式编码的音频文件的数据。

some.npy 是使用 sig = librosa.load(some_wav_file, sr=22050)np.save('some.npy', sig) 创建的。
我想转换这个 numpy 数组,就好像它的内容是用.mp3 编码的一样。

不幸的是,我仅限于使用内存中的文件对象,原因有两个。

  1. 我有很多.npy 文件。它们是预先缓存的,在实际运行应用程序时拥有这么多“真实”I/O 效率会非常低。
  2. 在服务器上执行应用程序的人员的访问权限存在冲突。

首先,我一直在寻找直接转换numpy数组中数据的方法,但是好像没有库函数。那么有没有一种简单的方法可以通过内存中的文件对象来实现这一点?

注意:我发现了这个问题How to convert MP3 to WAV in Python,它的解决方案理论上可以修改,但这不在内存中。

【问题讨论】:

    标签: python numpy audioformat


    【解决方案1】:

    您可以使用 BytesIO 读写内存,如下所示:

    import BytesIO
    
    # Create "in-memory" buffer
    memoryBuff = io.BytesIO()
    

    你可以使用pydub模块读写MP3:

    from pydub import AudioSegment
    
    # Read a file in
    sound = AudioSegment.from_wav('stereo_file.wav')
    
    # Write to memory buffer as MP3
    sound.export(memoryBuff, format='mp3')
    

    您的 MP3 数据现在可通过 memoryBuff.getvalue() 获得

    您可以使用this 答案在AudioSegments 和Numpy 数组之间进行转换。

    【讨论】:

    • 我无法直接使用它,因为我需要处理 numpy 数据,但我在 AudioSegment-wrapper 中找到了 audiosegment.from_numpy_array(nparr, framerate)。我现在的问题是 sound.export(memoryBuff, format='mp3') 返回一个 bytestr 而不是 numpy 数组。我尝试了多种方法将其转换为 numpy 数组(例如audiosegment.deserialize(bytestr),然后是您建议的pydub_to_np),但我得到了各种各样的错误。我怎样才能做到这一点?编辑:无论出于何种原因,np.frombuffer(bytestr) 以前没有用过……现在可以用了。
    • 抱歉,错误信息。 np.frombuffer(bytestr) 确实有效,但它会导致非常奇怪的值,这是可以理解的,因为 .export 调用返回的字节串编码了一个 mp3 文件并包含标题信息等,np.frombuffer(bytestr) 无法以合理的方式解释这些信息。如何以正确的方式将 bytestr 转换回 numpy 数组?
    【解决方案2】:

    我终于找到了一个可行的解决方案。这就是我想要的。

    from pydub import AudioSegment
    wav = np.load('some.npy')
    with io.BytesIO() as inmemoryfile:
            compression_format = 'mp3'
            n_channels = 2 if wav.shape[0] == 2 else 1 # stereo and mono files
            AudioSegment(wav.tobytes(), frame_rate=my_sample_rate, sample_width=wav.dtype.itemsize,
                         channels=n_channels).export(inmemoryfile, format=compression_format)
            wav = np.array(AudioSegment.from_file_using_temporary_files(inmemoryfile)
                           .get_array_of_samples())
    

    存在一个包装器包 (audiosegment),可以将最后一行转换为:

    wav = audiosegment.AudioSegment.to_numpy_array(AudioSegment.from_file_using_temporary_files(inmemoryfile))
    

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 2011-03-04
      • 2019-03-11
      • 2017-07-06
      • 2017-08-23
      • 1970-01-01
      • 2013-01-17
      • 2012-05-04
      • 1970-01-01
      相关资源
      最近更新 更多