Sunday, October 27, 2019

Making Slideshows w/FFMpeg

Browsing Reddit or StackOverflow and you come across numerous posts asking how to generate slideshows with FFMpeg.  Seems a common interest and incredibly easy with the right tools.  FFMpeg is one of the said tools,the other....makefiles.

There are few utilities that are truly hated in this industry, makefiles seem to be one of them.  Despite it's poor reputation, make is a perfect utility for many image and video processing pipelines.  I blame it's bad reputation on the hacks that claim to maintain them.  Make is the perfect utility, it's dependency engine is a perfect match for creating videos from input media.

This short little makefile will convert all JPGs in the current directory into subvideos of 1 sec durations, then concat them together into a long video and finally adding audio.

$ cat Makefile 
SRCS=${wildcard *.jpg}
SIZES=$(subst .jpg,.jpg.size,${SRCS})
CLIPS=$(subst .jpg,.mp4,${SRCS})

all: video.mp4

video.mp4: slideshow.mp4 audio.aac
${SH} ffmpeg -i slideshow.mp4 -i audio.aac -shortest -strict -2 $@

${SH} youtube-dl -f best
${SH} ffmpeg -i √ćslandsklukkur\ \(Instrumental\ Icelandic\ Folk\ Music\)-IYbE2coMZPc.mp4 -vn -codec copy audio.aac

slideshow.mp4: ${CLIPS}
${SH} for f in `echo $^`; do echo "file '$$f'" >> filelist.txt; done;
${SH} ffmpeg -y -f concat -i filelist.txt -codec copy $@
${RM} filelist.txt

%.mp4: %.jpg video.size background.jpg
${SH} ffmpeg -y -loop 1 -i background.jpg -i $< -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -r $(FPS) -vframes $(shell echo $(FPS)*$(SlideDuration) | bc) -an $@

video.size: ${SIZES}
${SH} echo $(shell cat *.size | cut -f 1 -d 'x' | sort -un | tail -1)x$(shell cat *.size | cut -f 2 -d 'x' | sort -un | tail -1) > $@

%.jpg.size: %.jpg
${SH} mogrify -auto-orient $<
${SH} identify $< | cut -f 3 -d ' ' > $@

background.jpg: video.size
${SH} convert -size $(shell cat $<) xc:black $@

${RM} *.mp4 *.size background.jpg *.aac

This makefile works for an arbitrary list of image sizes, it first auto-orients images (portrait/landscape) as it's not uncommon to have phone images mis-oriented.  It then generates a *.jpg.size file that contains the image dimensions.  These files are used next by the video.size target, which generates the maximum image size...this allows creating the video to match the largest of the images.  Next, a background jpg image is created of said dimensions.  Next, each image is converted into a 1 sec video which is then concatenated into the slideshow.mp4 file.  Finally, an audio video is created by downloading a video from Youtube and the audio is extracted, then applied to the slideshow mp4 file to get the final video.

I dumped our Iceland photo archive into the directory to test and it spit out the following video;

No comments:

Post a Comment