Как прочитать аудиофайл в формате MP3 в виде массива / сохранить массив в формате MP3? - PullRequest
0 голосов
/ 05 декабря 2018

Примечание: я уже прочитал Импорт звуковых файлов в Python в виде массивов NumPy (альтернативы audiolab) , перепробовал все ответы, включая те, которые требуют Popen ffmpeg, и прочитал содержимоеиз stdout pipe и т. д. Я также прочитал Попытка преобразовать mp3-файл в массив Numpy, а ffmpeg просто зависает и т. д., и попробовал основные ответы, но простого решения не было.Потратив несколько часов на это, я выкладываю это здесь со словами «Ответь на свой вопрос - поделись своими знаниями в стиле Q & A».Я также прочитал Как создать массив NumPy из Pydub AudioSegment? , но это нелегко охватить многоканальный случай и т. Д.


Есть ли способдля чтения / записи аудиофайла MP3 в / из массива numpy с API, аналогичным scipy.io.wavfile.read и scipy.io.wavfile.write ?

sr, x = wavfile.read('test.wav')
wavfile.write('test2.wav', sr, x)

Примечание: pydub объект *1023* не предоставляет прямой доступ к массиву numpy.

1 Ответ

0 голосов
/ 05 декабря 2018

Вызов 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...