Python:如何将mp3块解码为PCM样本? [英] Python: How to decode a mp3 chunk into PCM samples?
问题描述
我正在尝试捕获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屋!