我使用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])
然后,我的程序可以使用image变量。问题是,如果我从ffmpeg发送一个以上的图像,所有的数据都存储在这个变量中。我需要一种分离图像的方法。我能想到的唯一方法是分割jpeg标记文件结束(0xff, 0xd9)。这种方法有效,但并不可靠。关于带有子进程的管道文件,我错过了什么?有没有办法一次只从管道中读取一个文件?
对此的一个解决方案是使用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>
Where将恰好是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;这很重要,因为如果我们不这样做,标准错误缓冲区可能会被填满(因为没有任何东西正在读取它),并导致死锁。