Вызов ffmpeg
и ручной синтаксический анализ stdout
, как предлагается во многих постах о чтении MP3, является утомительной задачей (во многих сложных случаях, потому что возможно различное количество каналов и т. Д.), Поэтому вот рабочее решение, использующееpydub
(сначала нужно pip install pydub
).
Этот код позволяет считывать MP3 в массив numpy / записывать массив nupy в файл MP3 с API-интерфейсом, аналогичным scipy.io.wavfile.read/write
:
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', normalized=False)
print(x)
#[[-225 707]
# [-234 782]
# [-205 755]
# ...,
# [ 303 89]
# [ 337 69]
# [ 274 89]]
write('out2.mp3', sr, x, normalized=False)