Как использовать ffmpeg с Python, передавая файловые объекты (вместо местоположений в файлы на диске)

Я пытаюсь использовать ffmpeg с модулем подпроцесса Python для преобразования некоторых аудиофайлов. Я извлекаю аудиофайлы из URL и хотел бы просто передать файловые объекты Python в ffmpeg, вместо того, чтобы сначала сохранить их на диск. Также было бы очень хорошо, если бы я мог просто вернуть поток файлов вместо того, чтобы ffmpeg сохранил вывод в файл.

Для справки, вот что я делаю сейчас:

tmp = "/dev/shm"
audio_wav_file = requests.get(audio_url)
##              ##                         ##
## This is what I don't want to have to do ##
wavfile = open(tmp+filename, 'wrb')   
wavfile.write(audio_wav_file.content)
wavfile.close()
##              ##                         ##
conversion = subprocess.Popen('ffmpeg -i "'+tmp+filename+'" -y "'+tmp+filename_noext+'.flac" 2>&1', shell = True, stdout = subprocess.PIPE).stdout.read()

Кто-нибудь знает как это сделать?

Спасибо!

4 ответа

Решение

С ffmpeg вы можете использовать - в качестве имени файла ввода / вывода, чтобы указать, что он должен прочитать данные из stdin / write в stdout.

Тогда вы можете использовать stdin/stdout аргументы Popen читать / записывать ваши данные.

пример:

from subprocess import Popen, PIPE

with open("test.avi", "rb") as infile:
    p=Popen(["ffmpeg", "-i", "-", "-f", "matroska", "-vcodec", "mpeg4",
        "-acodec", "aac", "-strict", "experimental", "-"],
           stdin=infile, stdout=PIPE)
    while True:
        data = p.stdout.read(1024)
        if len(data) == 0:
            break
        # do something with data...
        print(data)
    print p.wait() # should have finisted anyway

вместо этого вы предоставляете файл для stdin Вы также можете использовать PIPE и записать непосредственно во входной поток процессов (p.stdin). или в вашем случае вы бы просто использовали wavfile...

обратите внимание, что вы должны явно указать формат вывода и кодеки, так как ffmpeg не может угадать их по расширению файла, как это обычно делается.
и это будет работать только для муксеров, которым не нужны выходные потоки с возможностью поиска, но flac должен работать...

Для тех, кто все еще читает это: это можно сделать без подпроцессов, используя вместо этого конвейерный протокол FFMPEG. Если FFMPEG вызывается с использованием пакетаffmpeg-python, то stdout, stderrвывод команды FFMPEG можно передать в переменные Python, как показано здесь:

out, err = inpstream.output('pipe:', ... ).run(capture_stdout=True)

Поскольку похоже, что вы работаете в Unix (нет.exe в конце 'ffmpeg'), я бы порекомендовал использовать именованный канал, иначе fifo:

mkfifo multimedia-pipe

Попросите сценарий Python записать аудиоданные в "мультимедийный файл" и попросить FFmpeg прочитать из того же файла. Я использовал этот шаблон для декодирования мультимедийных файлов в их огромные необработанные представления для проверки без необходимости занимать место на диске.

В качестве альтернативы попробуйте передать URL 'http: //...' непосредственно в опцию ввода FFmpeg.

PyAV можно использовать с путями или файловыми объектами из документации :

file (str) — файл для открытия, который может быть либо строкой, либо файлоподобным объектом.

(Если у вас есть массив байтов, вы можете обернуть егоio.BytesIOпрежде чем передать его av.open)

Другие вопросы по тегам