通过subprocess.PIPE接收ffmpeg的多个文件
我正在使用ffmpeg把视频转换成图片。这些图片接着会被我的Python程序处理。最开始,我是先用ffmpeg把图片保存到硬盘上,然后再用Python一个一个地读取它们。
这样做没问题,但为了加快程序的运行速度,我想跳过存储这一步,直接在内存中处理图片。
我用以下的ffmpeg和Python的子进程命令,把ffmpeg的输出直接传给Python:
command = "ffmpeg.exe -i ADD\\sg1-original.mp4 -r 1 -f image2pipe pipe:1"
pipe = subprocess.Popen(ffmpeg-command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
image = Image.new(pipe.communicate()[0])
这样,图片变量就可以被我的程序使用了。问题是,如果我从ffmpeg发送超过一张图片,所有的数据都会存储在这个变量里。我需要一种方法来分开这些图片。我能想到的唯一方法是根据jpeg文件的结束标记(0xff, 0xd9)来分割。这种方法虽然可行,但不太可靠。
我在使用子进程传输文件时,遗漏了什么呢?有没有办法一次只从管道中读取一张图片?
1 个回答
1
一种解决方案是使用ppm格式,这种格式的大小是可以预测的:
ffmpeg -i movie.mp4 -r 1 -f image2pipe -vcodec ppm pipe:1
这个格式的具体说明可以在这里找到:http://netpbm.sourceforge.net/doc/ppm.html
它的样子大概是这样的:
P6 # magic number
640 480 # width height
255 # colors per channel
<data>
其中的大小会是640 * 480 * 3字节(假设每个颜色通道的颜色不超过255种)。
需要注意的是,这种格式是未压缩的,所以如果你一次性读取所有数据,可能会占用相当多的内存。你可以考虑将你的算法改成:
pipe = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=sys.stderr)
while True:
chunk = pipe.stdout.read(4096)
if not chunk:
break
# ... process chunk of data ...
请注意,子进程的stderr
被设置为当前进程的stderr;这很重要,因为如果不这样做,stderr的缓冲区可能会被填满(因为没有人读取它),从而导致死锁。