Python:如何将mp3块解码为PCM样本? [英] Python: How to decode a mp3 chunk into PCM samples?

查看:103
本文介绍了Python:如何将mp3块解码为PCM样本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试捕获mp3网络流的大块并将其解码为PCM样本以进行信号处理.我试图通过请求和io.BytesIO捕获音频,以将数据另存为.wav文件.

I'm trying to catch chunks of an mp3 webstream and decoding them into PCM samples for signal processing. I tried to catch the audio via requests and io.BytesIO to save the data as .wav file.

我必须将mp3数据转换为wav数据,但我不知道如何.(我的目标不是录制.wav文件,我只是在测试算法.)

I have to convert the mp3 data to wav data, but I don't know how. (My goal is not to record a .wav file, i am just doing this to test the algorithm.)

我找到了pymedia库,但是它很旧(上一次提交是在2006年),使用的是python 2.7,对我来说不可安装.

I found the pymedia lib, but it is very old (last commit in 2006), using python 2.7 and for me not installable.

使用ffmpeg-python也许可以,但是我刚刚看到了使用文件作为输入和输出的示例.

Maybe it is possible with ffmpeg-python, but I have just seen examples using files as input and output.

这是我的代码:

import requests
import io
import soundfile as sf
import struct
import wave
import numpy as np


def main():
    stream_url = r'http://dg-wdr-http-dus-dtag-cdn.cast.addradio.de/wdr/1live/diggi/mp3/128/stream.mp3'
    r = requests.get(stream_url, stream=True)
    sample_array = []
    try:
        for block in r.iter_content(1024):
            data, samplerate = sf.read(io.BytesIO(block), format="RAW", channels=2, samplerate=44100, subtype='FLOAT',
                                       dtype='float32')
            sample_array = np.append(sample_array, data)

    except KeyboardInterrupt:
        print("...saving")
        obj = wave.open('sounds/stream1.wav', 'w')
        obj.setnchannels(1)  # mono
        obj.setsampwidth(2)  # bytes
        obj.setframerate(44100)

        data_max = np.nanmax(abs(sample_array))

        # fill WAV with samples from sample_array
        for sample in sample_array:
            if (np.isnan(sample) or np.isnan(32760 * sample / data_max)) is True:
                continue
            try:
                value = int(32760 * sample / data_max)  # normalization INT16
            except ValueError:
                value = 1
            finally:
                data = struct.pack('<h', value)
                obj.writeframesraw(data)

        obj.close()
        print("end")


if __name__ == '__main__':
    main()

您知道如何解决此问题吗?

Do you have an idea how to handle this problem?

推荐答案

Irmen 和他的帮助下"miniaudio"和"synthesizer"库,我可以解决问题.

With the help from Irmen and his "miniaudio" and "synthesizer" library, I could solve the problem.

问题在于,大多数广播网络流都使用ICECAST协议,该协议包含交错的元数据信息,因此您无法直接对其进行解码.

The problem was, that most radio webstreams uses the ICECAST protocol, which includes interleaved metadata information, so you can't decode it directly.

使用示例脚本 https://github.com/irmen/synthesizer/blob/master/examples/internetradio.py 作为模板,我可以编写一个脚本,该脚本记录一个Webstream直到KeyboardInterrupt并将其保存为.wav文件.

With the example script https://github.com/irmen/synthesizer/blob/master/examples/internetradio.py as template, I could write a script, which records a webstream until KeyboardInterrupt and saves it as a .wav file.

这是我编辑的主要部分:

Here's the main part I edited:

 ...

 def _audio_playback(self, pcm_stream):
    sample_array = None

    with Output(mixing="sequential", frames_per_chunk=44100 // 4) as output:
        print("begin recording")
        while self.decode_flag:
            try:
                audio = pcm_stream.read(44100 * 2 * 2 // 20)
                if not audio:
                    break
            except (IOError, ValueError):
                break
            else:
                sample = Sample.from_raw_frames(audio, 2, 44100, 2)
                if sample_array is None:
                    sample_array = sample.get_frames_numpy_float()
                else:
                    sample_array = np.append(sample_array, sample.get_frames_numpy_float(), axis=0)
        print("...saving")
        wavf.write(self.file_location, 44100, sample_array)
        print("saved")

...

这篇关于Python:如何将mp3块解码为PCM样本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆