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

2024-04-26 00:34:43 发布

您现在位置: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()

有人知道怎么做吗?

谢谢!


Tags: 模块文件tourl进程stdoutfilenameaudio
2条回答

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

然后可以使用Popenstdin/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提供一个文件,也可以使用PIPE并直接写入进程输入流(p.stdin)。或者你只需要使用wavfile。。。

注意,您必须显式地指定输出格式和编解码器,因为ffmpeg不能像通常那样从文件扩展名猜测它们。
它只适用于不需要可查看的输出流的muxer,但是flac应该可以工作。。。

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

mkfifo multimedia-pipe

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

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

相关问题 更多 >