如何通过传递文件对象(而不是位置到磁盘上的文件)来使用ffmpeg和Python

时间:2012-05-01 16:08:15

标签: python ffmpeg subprocess pyffmpeg

我正在尝试将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()

有谁知道怎么做?

谢谢!

3 个答案:

答案 0 :(得分:7)

使用ffmpeg,您可以使用-作为输入/输出文件名,以指示它应该从stdin读取数据/写入stdout。

然后,您可以使用stdin的{​​{1}} / 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)。或者在你的情况下,你只需使用wavfile ...

请注意,您必须明确指定输出格式和编解码器,因为ffmpeg无法像通常那样从文件扩展名中猜出它们。
它只适用于不需要可搜索输出流的多路复用器,但是flac应该可以工作......

答案 1 :(得分:2)

对于仍在阅读此内容的任何人: 可以通过使用FFMPEG's pipe protocol而不使用子过程来完成此操作。 如果使用包ffmpeg-python调用FFMPEG,则可以将FFMPEG命令的stdout, stderr输出输出到Python变量中,如here所示:

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

答案 2 :(得分:0)

因为看起来你是在Unix上('ffmpeg'末尾没有.exe),我建议使用命名管道,a.k.a。fifo:

mkfifo multimedia-pipe

让Python脚本将音频数据写入'multimedia-file'并让FFmpeg从同一个文件中读取。我使用这种模式将多媒体文件解码为巨大的原始表示形式,以便进行验证,而不必占用磁盘空间。

或者,尝试将'http:// ...'URL直接传递给FFmpeg的输入选项。