我正在使用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)。这有效,但不可靠。
对于使用子过程管道文件,我错过了什么?有没有办法只从管道中一次读取一个文件?
答案 0 :(得分: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缓冲区可能会填满(因为没有读取它)并导致死锁。