Почему длительность mp3 / wav отличается, когда я конвертирую массив numpy с ffmpeg в аудиофайл (python)? - PullRequest
1 голос
/ 03 февраля 2020

Я хочу преобразовать массив numpy, который должен содержать 60 секунд необработанного звука, в файлы .wav и .mp3. С помощью ffmpeg (версия 3.4.6) я пытаюсь преобразовать массив в нужные форматы. Для сравнения я также использую звуковой файл модуля. Только .wav-файл, созданный звуковым файлом, имеет ожидаемую длину, равную 60 с. .Wav-файл, созданный ffmpeg, немного короче, а .mp3-файл - ca. Длиной 32 с.

Я хочу, чтобы все экспорты были одинаковой длины. Что я делаю не так?

Вот пример кода:

import subprocess as sp
import numpy as np
import soundfile as sf

def data2audiofile(filename,data):
    out_cmds = ['ffmpeg',
                '-f', 'f64le', # input 64bit float little endian 
                '-ar', '44100', # inpt samplerate 44100 Hz
                '-ac','1', # input 1 channel (mono)
                '-i', '-', # inputfile via pipe
                '-y', #  overwrite outputfile if it already exists
                filename]
    pipe = sp.Popen(out_cmds, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) 
    pipe.stdin.write(data)


data = (np.random.randint(low=-32000, high=32000, size=44100*60)/32678).astype('<f8')

data2audiofile('ffmpeg_mp3.mp3',data)
data2audiofile('ffmpeg_wav.wav',data)
sf.write('sf_wav.wav',data,44100)

Здесь результирующие файлы отображаются в Audacity :

1 Ответ

2 голосов
/ 04 февраля 2020

Вам нужно закрыть pipe.stdin и дождаться окончания подпроцесса.

Закрытие pipe.stdin сбрасывает stdin трубу.
Тема объясняется здесь: Запись в python труба подпроцесса :

Ключ, чтобы закрыть стандартный ввод (flu sh и отправить EOF) перед вызовом wait

Добавить следующие строки кода после pipe.stdin.write(data):

pipe.stdin.close()
pipe.wait()

Вы также можете попробовать установить большой размер буфера в sp.Popen:

pipe = sp.Popen(out_cmds, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, bufsize=10**8)
...