通过subprocesses.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])
然后,我的程序可以使用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;这很重要,因为如果我们不这样做,标准错误缓冲区可能会被填满(因为没有任何东西正在读取它),并导致死锁。

最新更新