Blog-Archiv

Montag, 20. März 2023

Image to Video with ffmpeg

Sometimes you want to create a video clip from an image, for example a map of your recent backpacking trip that you want to insert into your trip video. This Blog contains a UNIX shell script to create an MP4 video from a given image file, and to add a silent audio-track to it.

You will have to install ffmpeg on your machine, and ImageMagick to scale the image.

Scripts

imageToVideo.sh

The resulting video will be in same directory as the image file, and will have the same name, but with extension ".MP4".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
##############################
# create a video from an image
##############################

frameRate=30/1
pixelFormat=yuv420p
inverseTimeBase=90000
keepTimeBase="-video_track_timescale $inverseTimeBase"
audioCodec=aac
audioSampleRate=48000

currentDir=`pwd`
cd `dirname \$0`	# change to where this script resides
PATH=$PATH:`pwd`	# take sibling scripts into path
cd $currentDir

syntax() {
	echo "SYNTAX: $0 imagefile [widthxheight [seconds]]" >&2
	echo "	Creates a video from an image." >&2
	echo "	widthxheight: image target dimension, default is 2336x1080" >&2
	echo "	seconds: the video duration, default is 4 seconds" >&2
	exit 1
}

[ -f "$1" ] || {
	echo "File not found: $1" >&2
	exit 2
}

imageFile="$1"
widthxheight=${2:-2336x1080}
videoSeconds=${3:-4}
videoFile="${imageFile%.*}".MP4	# filename without extension

rm -f $videoFile 2>/dev/null

scaledImageFile="`dirname \$imageFile`/scaled_`basename \$imageFile`"
imageToSize.sh "$imageFile" "$scaledImageFile" $widthxheight || exit 3

tmpVideoFile="`dirname \$videoFile`/tmp_`basename \$videoFile`"

cleanup()	{
	rm -f $scaledImageFile $tmpVideoFile
}
error()	{
	cleanup
	exit $1
}

echo "Creating a $videoSeconds seconds video from image ..." >&2
ffmpeg -y -v error -loop 1 \
	-i "$scaledImageFile" -c:v libx264 \
	-t $videoSeconds \
	-pix_fmt $pixelFormat -r $frameRate $keepTimeBase "$tmpVideoFile" || error $?

echo "Adding a silent audio track ..." >&2
ffmpeg -v error -y \
	-f lavfi -i anullsrc=sample_rate=$audioSampleRate:channel_layout=stereo \
	-i $tmpVideoFile \
	-c:v copy -c:a $audioCodec \
	-shortest "$videoFile" || error $?
	
cleanup
		
echo "Created $videoFile"

Lines 5 to 10 contain some video properties that you may want to change. You can display the properties of your trip video (frameRate, timeBase, pixelFormat, ...) by using the script videoProperties.sh from my article about ffmpeg utilities.

Lines 17 to 23 contain documentation for the script. Mind that the video dimension and duration parameters have default values and are just optional. The default dimension is 2336 x 1080 (width x height in pixels), the default duration is 4 seconds. When you want to specify the duration seconds, you also need to specify the dimension on command line.

Lines 25 to 28 check that the mandatory imagefile parameter is given and exists as a file.

Lines 30 to 33 pick up the command line arguments and put them into named variables, setting default values when none were given. The video file will be named like the image file, but with extension ".MP4" (see line 33).
Mind that the expression on line 33 is LINUX bash-specific and might not be supported by any kind of UNIX shell.

Lines 37 and 38 scale the image by using another script that needs to be in execution path, source code is below.

Line 40 creates a temporary filename for the video without audio track, to be removed later.

Lines 42 to 48 are functions that avoid code duplications.

Lines 50 to 54 now call ffmpeg to create the video without audio track. Mind the hardcoded parameter libx264 on line 52.

Lines 56 to 61 add the silent audio track.
(Sorry that I can't explain all those ffmpeg parameters, they are so many, I already forgot most of them; option "-i" always gives the input file; order of parameters is significant.)

Line 63 calls the cleanup function which removes all temporary intermediate files.
Line 65 finally outputs the name and location of the result video.

imageToSize.sh

The name and location of the resulting image must be given on comand line.
This script also was documented on another one of my Blog articles.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
####################################################
# Scales an image to a fixed size using ImageMagick.
####################################################

# defaultDimension=1920x1440
defaultDimension=1920x1080	# standard video dimension
edgeColor=black

syntax()	{
	echo "SYNTAX: $0 sourceImageFile targetImageFile [widthxheight]" >&2
	echo "	Scales an image to width x height, keeping aspect ratio, adding edges." >&2
	echo "	sourceImageFile: the image to scale" >&2
	echo "	targetImageFile: the result image file" >&2
	echo "	widthxheight: optional target dimension, default is $defaultDimension" >&2
	exit 1
}

[ -f "$1" -a -n "$2" ] || syntax
sourceImageFile="$1"
targetImageFile="$2"
dimension=${3:-$defaultDimension}	

echo "Scaling to $dimension from $sourceImageFile to $targetImageFile ..." >&2

# call ImageMagick
convert "$sourceImageFile" \
	-resize $dimension \
	-gravity center \
	-background $edgeColor \
	-extent $dimension \
	"$targetImageFile"

Lines 6 and 7 define some properties that you may want to change.
Mind that the default dimension here (1920 x 1440) is different from that of imageToVideo.sh above.

Lines 9 to 16 provide documentation for the script.

Line 18 to 21 check command line parameters and put them into named variables, also setting default values when needed.

Lines 26 to 31 finally call the convert tool of ImageMagick to do the work.
(Sorry, I forgot the meaning of all these parameters.)

Result will be an image of given dimension, centered, with black borders added where needed. Thus the result image won't be shrinked or stretched in any direction.

Resume

Mind that on UNIX you need to give execution rights to shell-scripts:

chmod u+x imageToVideo.sh imageToSize.sh

I hope this was helpful!