Filtering and sorting images passed to FFmpeg

My Foscam FI9900P IP-camera does not offer an option to only upload images to my server when it’s light out. Additionally, it does not create a directory for each date. Hence, I end up with a directory full of useless images made during the night that also grows enormously over time.

In my previous post, Converting weather cam images to video with FFmpeg, I shared a simple command that allows me to pass images based on file name to FFmpeg. Since then, I’ve made some additional tweaks and changes and added the command to my Java process.

For starters, I use the ‘find’ command to filter images based on creation date. The Meteodrenthe application is aware of sunrise and sunset times for my location, so I have the option to pass along those values to the command.

(As a side note, I’m not entirely happy with this solution, since those times don’t necessarily say much about the remaining light out. So I’ve ordered a couple of light sensors to try to get more specific data about how much light is still remaining so I can pick better moments to cut off the video. More to follow on that later.)

The command I use now is a bit different (and longer) compared to the original.

find <DIRECTORY> -name '*.jpg' -newermt '<yyyy-MM-dd HH:mm:ss>' ! -newermt '<yyyy-MM-dd HH:mm:ss>' -print | sort -n | xargs cat | ffmpeg -framerate 15 -f image2pipe -i - -c:v libx265 -b:v 2400k <TARGET_DIRECTORY>/output.mkv

There are several things to consider. <DIRECTORY> is the directory containing the images. There are 2 date parameters in format yyyy-MM-dd HH:mm:ss. Only images between those dates are passed along. Note that in this case only files ending with ‘.jpg’ are considered. If the directory contains other image formats, this needs to be changed. Then, ‘-print’ will cause the ‘find’ command to output the result with each record on a new line. This is important. Using ‘-print0’ won’t work, because the sort command requires the results to be on their own line. The entire result is piped to ‘sort -n’, which sorts the results according to their numerical value. This works in my case, because all files are the same except for the date and time values, which are incremental. After sorting, ‘xargs cat’ will take the result and run the ‘cat’ command on it, which is then passed to FFmpeg as in the original case. The ‘ffmpeg’ has some variables like bitrate (at 2400k now) and framerate (value is 15 in the example). <TARGET_DIRECTORY> dictates where the video out file ‘output.mkv’ will be sorted.

Why am I even sorting the result? I noticed that when using the ‘mv’ command to move all images for a specific date to its own directory (i.e. all images for November 9th 2020 to ./2020/11/9/), FFmpeg would no longer properly process the images sorted by date. While the modification date is unchanged, other timestamps do change. For example, running ‘stat <file>’ would show an identical ‘Modify’ value, but the timestamp for ‘Change’ takes on the time when the file was moved. The ‘mv’ command has no option to retain this, and the command ‘cp -p’ (copy with the preserve timestamps option) seems to do something similar. Hence, forcing sorting seemed the safest choice.

Leave a Reply

Your email address will not be published. Required fields are marked *