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

如何通过传递文件对象(而不是将位置传递到磁盘上的文件)将ffmpeg与Python结合使用,python,ffmpeg,subprocess,pyffmpeg,Python,Ffmpeg,Subprocess,Pyffmpeg,我正在尝试使用ffmpeg和Python的子流程模块来转换一些音频文件。我从一个URL抓取音频文件,只希望能够将Python文件对象传递到ffmpeg,而不是首先将它们保存到磁盘。如果我能得到一个文件流,而不是让ffmpeg将输出保存到一个文件中,那将是非常好的 作为参考,这是我现在正在做的: tmp = "/dev/shm" audio_wav_file = requests.get(audio_url) ## ## #

我正在尝试使用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()
有人知道怎么做吗


谢谢

因为看起来您是在Unix上(“ffmpeg”末尾没有.exe),所以我建议使用命名管道,也称为fifo:

mkfifo multimedia-pipe
让Python脚本将音频数据写入“多媒体文件”,并让FFmpeg读取同一文件。我使用这种模式将多媒体文件解码为巨大的原始表示,以进行验证,而无需占用磁盘空间


或者,尝试通过'http://...'直接指向FFmpeg的输入选项的URL。

使用FFmpeg,您可以使用
-
作为输入/输出文件名,指示它应该从标准输入/写入标准输出读取数据

然后可以使用
Popen
stdin
/
stdout
参数来读取/写入数据

例如:

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
提供一个文件,也可以使用
管道
直接写入进程输入流(
p.stdin
)。或者在您的情况下,您只需使用wavfile

请注意,您必须明确指定输出格式和编解码器,因为ffmpeg无法像通常那样从文件扩展名猜测它们。

它只适用于不需要可查找的输出流的多路复用器,但flac应该适用于…

任何仍在阅读本文的人: 这可以在没有子流程的情况下通过使用来完成。 如果使用包
FFMPEG-python
调用FFMPEG,则FFMPEG命令的
stdout、stderr
输出可以输入到python变量中,如图所示:

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