Under construction!
Summary. This note explains how to create animations from a series of individual plots.
The animations are realized in several formats relevant for today's
web browsers and PDF viewers: animated GIF, MP4, WebM, Ogg, and Flash.
The tools used to create video files are convert
, ffmpeg
or avconv
,
and mencoder
.
Suppose we have a set of image files containing a curve that moves. Two such images are displayed in Figure ref{animate:fig:frames}. In our particular example, the animation shows the evolution of a function \( f(x,t) \) in time \( t \), where the the individual plots correspond to different values of \( t \).
Our aim is to combine the individual image files to a movie file that can be shown in a web page, a PDF document, or simply just played by a video player on a computer.
Filenames.
In the forthcoming examples, the individual plot files are stored in a
subdirectory frames and have filenames frame_0000.png
,
frame_0001.png
, frame_0002.png
, and so on. The plot files were
generated in some program that used the printf syntax frame_%04d.png
to specify the filenames. Note that the padding with zeros is
important if we want a Unix wildcard notation frame_*.png
to list
the files in correct order (without padding, frame_21.png
appears
before frame_2.png
in a standard alphanumeric sorting).
We assume in the following that all our frames are stored as files
frame_*.png
in a subdirectory frames
.
Terminal> ls -1 frames
frame_0000.png
frame_0001.png
frame_0002.png
frame_0003.png
frame_0004.png
frame_0005.png
frame_0006.png
frame_0007.png
frame_0008.png
frame_0009.png
frame_0010.png
frame_0011.png
...
frame_0313.png
frame_0314.png
frame_0315.png
frame_0316.png
frame_0317.png
frame_0318.png
frame_0319.png
frame_0320.png
Video formats.
The relevant video formats are dictated by the media we want to use to
display the video. In web pages, modern HTML5 has support for video,
but it is recommended to have the video available in three formats to
cover the most common browsers and devices: MP4, WebM, and Ogg.
HTML pages can also show animated GIF files. Flash files can
be uploaded to YouTube or Vimeo and embedded in any HTML file. In PDF documents
produced from LaTeX, the media9
package is the current standard. It
supports embedded movies in MP4 or Flash format to be displayed by
Acrobat Reader version 9 and later.
The following text provides a lot of Unix commands for creating movies as batch processes. All commands are collected in the shell script session.sh.
Animated GIF files can be made by the convert program from the
ImageMagick suite.
Making an animation with 12 frames per second in the file
demo_convert.gif
is done by
Terminal> convert -delay 8 frames/frame_*.png demo_convert.gif
The -delay
option specifies the number of 0.01 seconds between each
frame, so if we want 12 frames per second, the delay becomes \( 100/12
\approx 8 \). One can add the option -loop 0
to make the animation
repeat forever.
The animated GIF file is displayed through an ordinary image tag in HTML:
<img src="demo_convert.gif" width=500>
Alternatively, one can run animate demo_convert.gif
to watch the
movie on the screen.
With a lot of frames, especially when each frame has a significant size,
convert
needs substantial computational resources to make the animated
GIF file, and the filesize easily becomes huge (essentially the sum
of the GIF versions of the PNG files in this example). The
corresponding loading time in HTML or in the animate
application
is significant. Hence, animated GIF files are best suited for smaller
file collections.
[hpl 1: `convert` is killed when trying to make the demo animation; it is too big for my Mac 11''.]
ffmpeg
to make MP4, WebM, Ogg, Flash, AVI, and MPEG files
ffmpeg
program runs on all major platforms, but Debian-based
Linux systems offers the almost equivalent program avconv
instead.
All ffmpeg
commands below work with avconv
, just replace the
program name.
The basic ffmpeg
command for producing a movie file with
name movie.ext
, in the format
implied by the extension .ext
, reads
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png \
-c:v libcodec movie.ext
The -r
option sets the number of frames per second (and should
come first), -i
lists the individual frames, with the filenames parameterized
according to the printf syntax, and -c:v
specifies the
codec for video to be used). The relevant extensions of the movie file are
.mp4
for MP4, .webm
for WebM, .ogg
for Ogg, '.mpeg' or '.mpg'
for MPEG, and '.avi' for AVI.
Video files are compressed and therefore need a codec to compress and decompress
the contents. One should specify the codec explicitly to make sure
the same codec is used for making the movie and for playing it.
For the MP4 format it is common now to use the H.264 standard,
which is implemented in the open source library x264
. The
Ogg format should be made with the libtheora
(for video)
and libvorbis
(for audio) codecs. The Google-sponsored WebM
format applies the libvpx
codec (for video) and
the libvorbis
codec (for audio).
Creating MP4 video.
The ffmpeg
command for MP4 movies with the H.264 codec is
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png \
-c:v libx264 movie1.mp4
The -r
option governs the number of frames per second, here 12.
The -i
option indicates the set of input files, here specified
with printf syntax (the same syntax as was used to make the files).
The option for the audio codec (-c:a
) can be skipped when there is
no sound.
The resulting file can be shown in a video player, such as vlc, mplayer, gxine, or totem on Linux platforms: [hpl 2: add mac here, test in windows media player]
Terminal> vlc movie1.mp4
Terminal> mplayer movie1.mp4
Terminal> gxine movie1.mp4
Terminal> totem movie1.mp4
[hpl 3: Some doc (the doc of the media9 package to be specific) claims
that keyint=12
is important (one key frame per second for effective
video searching), but ffmpeg
on Ubuntu does not recognize this option.
Is it available on Mac?]
[hpl 4: On my Ubuntu, ffmpeg
does not recognize the -x264opts
option.
It did not recognize libx64
but suddenly it did, and later it did not...]
Creating WebM video.
The relevant ffmpeg
command video in the WebM format is
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png \
-c:v libvpx movie1.webm
Add -c:a libvorbis
if the movie features audio as well.
Creating Ogg video.
The proper ffmpeg
command for Ogg video is
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png \
-c:v libtheora movie1.ogg
Add -c:a libvorbis
for audio.
Creating Flash video.
The Flash format is produced by the ffmpeg
command
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png -c:v flv movie1.flv
Creating AVI video. The AVI format is produced by the command
Terminal> ffmpeg -r 12 -i frames/frame_%04d.png movie1.avi
Creating MPEG video. The MPEG format does not allow the frame rate to be specified and there is no need for specifying the code:
Terminal> ffmpeg -i frames/frame_%04d.png -c:v mpeg4 movie1.mpeg
ffmpeg -codecs
lists all available codecs.
[hpl 5: All installed
or all available in theory?]
avconv
to make MP4, WebM, Ogg, and Flash files
Exactly the same commands as for ffmpeg
.
mencoder
to make MP4, WebM, and Ogg files Below are some collected sketches of how to work with mencoder...
cmd = "mencoder mf://tmp/* -mf type=%(TYPE)s:fps=%(FPS)f -o "%(OUT)s" -ovc lavc "
cmd % { 'FPS': (1.0/options.spf),
'OUT': options.out,
'TYPE': imagetype }
mencoder -vf -ovc x264 -x264encopts -lavfopts format=mp4 -o movie.mp4
Terminal> mencoder 'mf://*.jpg' -mf fps=25 -o output.avi \
-ovc lavc -lacvopts vcodec=msmpeg4v2
Terminal> mencoder 'mf://animation/*.png' -mf fps=25:type=png \
-ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell -oac copy -o huygen.avi
Terminal> mencoder 'mf://*.png' -mf type=png:fps=10 -ovc \
lavc -lavcopts vcodec=wmv2 -oac copy -o animation.avi
Terminal> mencoder mf://*.png -mf type=png:w=800:h=600:fps=25 \
-ovc lavc -lavcopts vcodec=mpeg4 -oac copy -o output.avi # older
The easiest way of playing a movie is to have it available on YouTube since any browser is capable of playing a YouTube video.
Video files can be uploaded manually...
The youtube-upload script by Arnau Sanchez automates uploading a video to YouTube.
Terminal> youtube-upload --email=myemail@gmail.com \
--password=mypassword \
--title="Wave Motion in Discontinuous Media" \
--description="Finite difference method" \
--category=Science \
--keywords="finite differences, waves" \
movie1.flv
The web URL of the movie appears as output from the script.
See the README file.
Many will prefer to use a dedicated YouTube channel with its own
name for publishing certain types of movies. To make a channel, go to
youtube.com, sign in with your Google account,
click on the down arrow to the right of your your icon/picture,
choose All my channels to see your YouTube channels, click Create a
new channel, and fill in the fields. You will receive an email
where the "from" address contains the mail address of the new channel
that can be used when uploading movies via the youtube-upload
script.
[hpl 6: Possible, but no user-friendly script found.]
A web page can play a series of image files as an animation with the aid of some JavaScript code. A typical example on such code goes as
<script language="Javascript">
var num_images_movie = 321;
var img_width = 800;
var img_height = 600;
var interval = 300;
var images_movie = new Array();
function preload_images_movie()
{
t = document.getElementById("progress");
t.innerHTML = "Preloading image ";
images_movie[0] = new Image(img_width, img_height);
images_movie[0].src = "frames/frame_0000.png";
t.innerHTML = "Preloading image ";
images_movie[1] = new Image(img_width, img_height);
images_movie[1].src = "frames/frame_0001.png";
...
t.innerHTML = "Preloading image ";
images_movie[320] = new Image(img_width, img_height);
images_movie[320].src = "frames/frame_0320.png";
t.innerHTML = "";
}
function tick_movie()
{
if (frame_movie > num_images_movie - 1)
frame_movie = 0;
document.movie.src = images_movie[frame_movie].src;
frame_movie += 1;
tt = setTimeout("tick_movie()", interval);
}
Some buttons for controls can easily be added:
<form>
<input type="button" value="Start movie" onClick="startup_movie()">
<input type="button" value="Pause movie" onClick="stopit()">
<input type="button" value="Restart movie" onClick="restart_movie()">
<input type="button" value="Slower" onClick="slower()">
<input type="button" value="Faster" onClick="faster()">
</form>
<p><div ID="progress"></div></p>
<img src="frames/frame_0000.png" name="movie" border=2/>
where the JavaScript functions called by the buttons are defined as
function startup_movie()
{
preload_images_movie();
frame_movie = 0;
setTimeout("tick_movie()", interval);
}
function stopit()
{ clearTimeout(tt); }
function restart_movie()
{ tt = setTimeout("tick_movie()", interval); }
function slower()
{ interval = interval/0.7; }
function faster()
{ interval = interval*0.7; }
</script>
The program html_player.py generates this type of JavaScript code and is run like
Terminal> python html_player.py frames/frame_*.png > player.html
You can now load player.html
into a browser to see the movie, or
click here.
video
tag
To display a specific video file, say movie1.webm
, the relevant
HTML5 command is
<video autoplay loop controls
width='640' height='365' preload='none'>
<source src='movie1.webm' type='video/webm; codecs="vp8, vorbis"'>
</video>
The autoplay
command makes the video play when the page is loaded.
You may not want this feature. The loop
command causes the video to
repeat forever, while controls
inserts some basic controls for
playing, pausing, full screen viewing, etc.
The fundamental problem with the video
tag in HTML5 is that
it does not work with any format in any browser on any type of device.
A common recommendation is to make the videos in three formats,
MP4, WebM, and Ogg, and specify all three as possible formats:
<div>
<video autoplay loop controls
width='640' height='365' preload='none'>
<source src='movie1.mp4' type='video/mp4;
codecs="avc1.42E01E, mp4a.40.2"'>
<source src='movie1.webm' type='video/webm;
codecs="vp8, vorbis"'>
<source src='movie1.ogg' type='video/ogg;
codecs="theora, vorbis"'>
</video>
</div>
The MP4 file is specified first, because on iOS devices (iPhone/iPad) only one source is loaded, but these devices play MP4 files.
embed
tag
Prior to HTML5 one used the embed
tag to embed movies. The browser
then relies on some player on the system. Successful playing of a video
relies on
correct configuration of the browser with an appropriate movie player.
The embed
tag looks like
<embed src="movie1.mpeg" width='640' height='365'
autoplay="true" loop="true"></embed>
media9
Ubuntu and other Debian-based
Linux versions support avconv
instead of ffmpeg
.
The basic packages for installing avconv
are
libav-tools
libavcodec-extra-53
libx264-dev
Various players are installed by
mplayer gnome-mplayer
mencoder
totem totem-plugins totem-mozilla
vlc browser-plugin-vlc
gxine python-pyxine xine-plugin libxine2-dev libxine2-all-plugins
gxine-plugin libxine2-ffmpeg
swfdec-gnome flashplugin-installer
Install scripts that runs sudo apt-get install
on the above
packages are found in
Bash and
Python.
Check https://help.ubuntu.com/community/Medibuntu
Problems may arise for ffmpeg
or avconv
run with libx264
.
If that encoder cannot be find, try a manual installation as
described next.
[hpl 7: This did not work for me on Ubuntu 12.04.]
# Remove existing libx264 libs
sudo apt-get remove libx264-dev libx264-120
# Compile source in a new directory
mkdir ~/avconv-source
cd ~/avconv-source
git clone git://git.videolan.org/x264.git
cd x264
./configure --enable-static --disable-asm
make
sudo make install
cd ..
git clone git://git.libav.org/libav.git
cd libav
./configure
./configure --enable-gpl --enable-static --enable-shared \
--enable-libx264 --enable-libvpx --enable-libtheora
make
sudo make install
cd ..
# avconv -i test.mov -c:v libx264 -c:a copy test.mp4
Useful links for installing ffmpeg:
http://www.renevolution.com/how-to-install-ffmpeg-on-mac-os-x/