The goal#
Given a series of images, present them in a video with a blend effect between the images. The frames between the input frames should gradually transition between the previous and next image. This, and other transition effects, could likely be implemented using a slideshow generator, but it can also be done quite easily using a shell script.
The script#
The final script I wrote is blend.sh
. The following commands fetch
and run it:
$ wget https://gist.githubusercontent.com/dperelman/2b4b86233aa13d13c0ab/raw/91c7988e27288af8aeb25ade11d0cab90355702f/blend.sh
$ chmod +x blend.sh
$ ./blend.sh slideshow.mkv first.png second.jpg third.gif
$ mplayer slideshow.mkv
The input images may be in any format. The extension of
slideshow.mkv
will be used by FFmpeg to guess the desired
video format (H.264 in a Matroska Multimedia Container for
.mkv
).
The details#
FFmpeg#
To encode a video from the command line, the relevant tools are FFmpeg and MEncoder. I choose FFmpeg because I generally find it easier to use, but I tend to switch between the two when one isn't doing what I want.
We reduce the problem of generating a video to one of generating the frames for that video using the FFmpeg input mode image2, which takes in a sequence of images as the frames for a video.
ImageMagick#
To generate the frames, we will use the ImageMagick family of tools, which are a set of command-line tools that will do pretty much any image manipulation task you can imagine. The primary downside of ImageMagick is that it does so much, it sometimes takes a bit of reading through the documentation to figure out the right settings for a simple task.
The basic ImageMagick command is convert
. In the
script, it is used to convert the input image from
any format ImageMagick supports to a PNG
(the frames are stored as PNG because it uses
lossless compression):
convert "$image" "$dir/image${num}.png"
Blending#
ImageMagick's composite
command with the
-blend
option is used to make the intermediate frames. See
the examples section of the ImageMagick documentation for
how to use -blend
.
The code for performing the blend is1
# Use bc for math to get decimals.
percent="$(echo "$fade_amount/$frames_per_image*100" \
| bc -lq)"
composite -blend "$percent" "$image" "$prev" \
"$dir/image$num"".png"
The computation of $percent
is done with
bc
in order to get decimals:
$ fade_amount=7
$ frames_per_image=30
$ echo "$fade_amount/$frames_per_image*100"
7/30*100
$ echo $((fade_amount/frames_per_image*100))
0
$ echo $((100*fade_amount/frames_per_image))
23
$ echo "100*$fade_amount/$frames_per_image" | bc
23
$ echo "$fade_amount/$frames_per_image*100" | bc -l
23.33333333333333333300
Cleaning up#
The script make a temporary directory using mktemp
-d
and deletes it using rm -rf
when it is done.
This means the script writes the frames it generates to a directory
in /tmp
, so if using this to create a video for many images, make
sure you have enough space in /tmp
for the frames or use the -p
option of mktemp
to place the temporary directory somewhere
there is enough space. The frames will take approximately
$frames_per_image
(default=30) times as much space as
the input images.
-
Actually, this is all on one line in the script, but it's easier to read this way. ↩
Comments
Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.
There are no comments yet.