Which methods exist to animate a cartoon in latex and convert it into a video format like .mp4?
2 Answers
Creating an animation as multi-page PDF
One possibility to create a multi-page PDF with an animation is to use beamer. With its ability to use overlays it is easy to create image sequences like the following example:
\documentclass{beamer}
\usepackage{tikz}
\setbeamertemplate{navigation symbols}{}
\usetikzlibrary{overlay-beamer-styles}
\usepackage{tikzlings}
\begin{document}
\begin{frame}[label=jump]
\begin{tikzpicture}[remember picture, overlay]
\foreach \x in {0,5,...,180}{
\only<+>{
\begin{scope}[yshift=sin(\x)*1cm,xshift=\thepage/\insertdocumentendpage*18cm]
\marmot[xshift=-1.2cm,yshift=-2.8cm]
\end{scope}
\draw[thick]
(-3.7+\thepage/\insertdocumentendpage*18, 0.6) .. controls
(-3.7+\thepage/\insertdocumentendpage*18, 0.6) and
(-3.5+\thepage/\insertdocumentendpage*18, -0.5) ..
(-1.5+\thepage/\insertdocumentendpage*18, {sin(\x)-2});
}
}
\shade[ball color=red] (-3.7+\thepage/\insertdocumentendpage*18,1.4) ellipse (0.5 and 0.9);
\end{tikzpicture}
\end{frame}
\againframe{jump}
\againframe{jump}
\againframe{jump}
\againframe{jump}
\againframe{jump}
\end{document}
Converting the multipage PDF into a movie
To convert a multi-page pdf one can for example use the following bash script. It uses the convert command from ImageMagick, the Handbreak video transcoder and the video and audio software ffmpeg.
# clean up old video
rm test.mp4
# convert to png images
# is called something different in windows, `magick convert` ?
convert -density 160 test.pdf test.png
# convert to video
# modify -r 10 to adjust the speed in which the individual images are shown
# combine the video with music starting at second 16: -ss 00:00:16 -i FunnyMusic.mp3
ffmpeg -r 10 -ss 00:00:00 -i test-%d.png -ss 00:00:16 -i FunnyMusic.mp3 -shortest test_raw.mp4
# repair video, add preview image etc.
HandBrakeCLI --crop 0:0:0:0 -i test_raw.mp4 -o test.mp4
# clean up
rm test-*.png
rm test_raw.mp4
# view :)
open test.mp4
Result
Example
An example of some animated cartoon scenes, most using the same technique as described above, can be found at https://vimeo.com/305374856
(the source code is available from https://github.com/samcarter/Extravanganza2018)
- 158,329
-
2Impressive... impressive... CRAZY! – Daniel Dec 09 '18 at 23:10
I've written a conversion script which takes a tikz animation and converts it to a mp4 file. It does so by manipulating the TeX source to set the snapshot functionality of tikz for each frame of the animation and then let TeX render them. The output is then converted to png with imagemagick and finally joined with fmmpeg. I've done quite a lot of optimisation (parallel execution of the TeX processes) and used it a couple of times myself. Feel free to check it out: https://github.com/nitardus/tikz2mp4
EDIT: Just in case, here is a simplified verson of the script:
#! /usr/bin/perl
use v5.14;
use strict; use warnings;
use Cwd;
use File::Spec;
use File::Temp;
my $duration = 5.5; # length of your animation (in seconds);
my $fps = 25; # frameratr
my $density = 300; # resolution
my $texcommand = 'lualatex';
my $videolib = 'libx264';
my $dir = getcwd();
my $tempdir = File::Temp->newdir();
my $filename = $ARGV[0] or die "You must specify a LaTex file for input!\n";
$filename =~ s/.tex//;
COMMAND NAMES
my @tex = ($texcommand, '-output-directory', $tempdir);
my @convert = ('magick', 'convert', '-background', 'white', '-alpha', 'remove',
'-alpha', 'off', '-density', $density);
my @identify_h = ('magick', 'identify', '-ping', '-format', "'%h'");
my @identify_w = ('magick', 'identify', '-ping', '-format', "'%w'");
my @mogrify_h = ('magick', 'mogrify', '-chop', '0x1');
my @mogrify_w = ('magick', 'mogrify', '-chop', '1x0');
my @ffmpeg = ('ffmpeg', '-y', '-framerate', $fps,
'-pattern_type', 'glob', '-i', '*.png',
'-c:v', $videolib, '-pix_fmt', 'yuv420p');
get contents of the .tex file, prepare it
my $buffer = '';
while (<>) {
Skip comments and empty lines
next if m/^\s%/ or m/^\s$/;
Add the snapshot option to the tikzpicture environment
if ( s! \begin{tikzpicture} \s* [
!$&make snapshot of = ###, !x
) {}
elsif ( s! \begin{tikzpicture}
!$&[make snapshot of = ###]!x
) {}
$buffer .= $_;
}
compute time values, add to @queue
my @queue;
for my $sec (0..int ($duration - 1)) {
for my $frac (0..($fps - 1)) {
my $time = $frac / $fps + $sec;
push @queue, "$time" . "s";
}
}
push @queue, ( int $duration ) . 's';
make list of output filenames
my $width = length scalar @queue;
my @filenames;
for my $number (0..$#queue) {
my $format = "%0$width" . "d-$filename";
my $name = sprintf $format, $number;
push @filenames, "$name";
}
for my $frm (0..$#queue) {
say STDERR "Rendering frame for: $queue[$frm]";
my $buf = $buffer =~ s/###/$queue[$frm]/gr;
my $texinput = File::Spec->catfile($tempdir, "$filenames[$frm].tex");
open my $tex_fh, '>', $texinput
or die "Cannot open $filenames[$frm].tex for.write: $!\n";
print { $tex_fh } $buf;
close $tex_fh;
!system @tex, $texinput
or die "LATEX ERROR while processing frame $filenames[$frm]!";;
unlink "$filenames[$frm].tex";
RUN IMAGEMAGICK
my $pdf_file = File::Spec->catfile($tempdir, "$filenames[$frm].pdf");
my $png_file = File::Spec->catfile($tempdir, "$filenames[$frm].png");
convert pdf to png; die on non-zero exit value
!system @convert, $pdf_file, $png_file
or die "IMAGEMAGICK ERROR while processing frame $filenames[$frm]!";
chop one row of pixels if the height is odd
my $height = @identify_h $png_file;
my $width = @identify_w $png_file;
system @mogrify_h, $png_file if $height % 2;
system @mogrify_w, $png_file if $width % 2;
}
chdir $tempdir;
my $output_file = File::Spec->catfile($dir, "$filename.mp4");
system @ffmpeg, $output_file;
unlink glob "$filename.";
chdir $dir;
unlink $tempdir;
Make sure to have both imagemagick and ffmpeg installed, put this script in a file (say tikz2mp4) and execute it on your .tex file (say example.tex) with
perl tikz2mp4
See here for an example (source modified from the official tikz animation documentation.
- 21
- 3

