As part of a personal project I’ve been toying with I wanted to be able to generate images using a naming convention where the image name would describe the frame order. For example: frame-1.png
, frame-2.png
, … frame-100.png
.
The directory the frame images were stored in were, themselves, named according to an ordered convention as well. The entire structure would look like:
+ gen-1
- frame-1.png
- frame-2.png
- frame-3.png
+ gen-50
- frame-1.png
- frame-2.png
- frame-3.png
+ gen-100
- frame-1.png
- frame-2.png
- frame-3.png
This structure would serve as the input to a tool that will create 3 videos: gen-1.mp4, gen-50.mp4, and gen-100.mp4 each of which are 3 frames long (in reality the videos are longer but it just means more frame files).
I’m not the command line guru so this is the approach I took to figure this out:
Generate a Video From a Directory of Images
I started by trying to find a command, using ffmpeg, that would create a video for the directory gen-1 with the following properties:
Feature | Desired |
---|---|
FPS | 30 |
Format | mp4 |
Resolution | 1280x1280 |
ffmpeg -framerate 30 -f image2 -s 1280x1280 -i gen-1/frame-%d.png -vcodec libx264 -pix_fmt yuv420p -y gen-1.mp4
Argument | Value | Outcome |
---|---|---|
-framerate | 30 | Sets the framerate to 30 |
-f | image2 | The input format is images |
-s | 1280x1280 | The frame size of the input images |
-i | gen-1/frame-%d.png | The input frame images |
-vcodec | libx264 | Encodes using the x264 video format (mp4) |
-pix_fmt | yuv420p | Without this the video wouldn’t load in Quicktime |
-y | none | Overwrites output files |
gen-1.mp4 | none | The name of the output file |
List all the Directories
find gen-* -type d
This command will identify the three directories following the convention described above.
% find gen-* -type d
gen-1
gen-50
gen-100
Tie Them Together
Now that I can produce the video - but need the directory names - and I can produce a list of directory names, I want to tie them together.
find gen-* -type d | xargs -I {} echo {}
gen-1
gen-50
gen-100
I used xargs to pipe the output of find into the input of xargs and then kick off the child process - in this example simply echoing the inputs.
So let’s stitch them together
find gen-* -type d | xargs -I {} ffmpeg -framerate 30 -f image2 -s 1280x1280 -i {}/frame-%d.png -vcodec libx264 -pix_fmt yuv420p -y {}.mp4
And the output is a video that does exactly what I had hoped.