Как использовать 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
)