Per Plexi
Per Plexi

Reputation: 43

Receiving multiple files from ffmpeg via subprocesses.PIPE

I am using ffmpeg to convert a video into images. These images are then processed by my Python program. Originally I used ffmpeg to first save the images to disk, then reading them one by one with Python.

This works fine, but in an effort to speed up the program I am trying to skip the storage step and only work with the images in memory.

I use the following ffmpeg and Python subproccesses command to pipe the output from ffmpeg to 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])

The image variable can then be used by my program. The problem is that if I send more than 1 image from ffmpeg all the data is stored in this variable. I need a way to separate the images. The only way I can think of is splitting on jpeg markers end of file (0xff, 0xd9). This works, but is unreliable.

What have I missed regarding piping files with subproccesses. Is there a way to only read one file at a time from the pipeline ?

Upvotes: 4

Views: 1908

Answers (1)

David Wolever
David Wolever

Reputation: 154494

One solution to this would be to use the ppm format, which has a predictable size:

ffmpeg -i movie.mp4 -r 1 -f image2pipe -vcodec ppm pipe:1

The format is specified here: http://netpbm.sourceforge.net/doc/ppm.html

And looks something like this:

P6      # magic number
640 480 # width height
255     # colors per channel
<data>

Where will be exactly 640 * 480 * 3 bytes (assuming there are 255 or fewer colors per channel).

Note that this is an uncompressed format, so it may potentially take up quite a bit of memory if you read it all at once. You may consider switching your algorithm to:

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 ...

Note that the subprocess' stderr is set to the current process' stderr; this is important because, if we don't, the stderr buffer could fill up (as nothing is reading it) and cause a deadlock.

Upvotes: 2

Related Questions