A faster way to grab frames from video using ffmpeg

In the zoomGroupStats functions that I described in this post, there is a function for identifying and analyzing faces. The original version that I posted uses ImageMagick to pull image frames out of video files. This is embedded in the videoFaceAnalysis function. In practice, this is a very inefficient method for breaking down a video file before sending it off to AWS Rekognition for the face analysis. I’ve found that ImageMagick takes quite a long time to pull images from a video.

As an alternative, I’ve been using ffmpeg to process the video files before using the zoomGroupStats functions. I love ffmpeg and have used it for years to manipulate and process audio and video files. After you have installed ffmpeg on your machine, you can use system(“xxxx”) in the stream of your R code to execute ffmpeg commands. For example, here’s what I include in a loop that is working through a batch of video files:

ffCmd = paste("ffmpeg -i ", inputPath, " -r 1/", sampleWindow, " -fimage2 ", outputPath, "%0d.png", sep="")

Then, you can just run system(ffCmd) to execute this line. In the line, inputPath is the path to the video file, sampleWindow is the number of seconds that you would like between each frame grab, and outputPath is the path to the directory, including an image name prefix, where you want the images saved.

Using a computer that isn’t very powerful (a Mac Mini), I was able to break down 20 ~2 hour videos (about 2400 minutes of video) into frame grabs every 20 seconds (around 7000 images) in less than an hour.

I will end up replacing ImageMagick with ffmpeg in the next iteration of the videoFaceAnalysis function. This will also come with the output of new metrics (i.e., face height/width ratio and size oscillation). Stay tuned!