15

Which methods exist to animate a cartoon in latex and convert it into a video format like .mp4?

2 Answers2

18

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

enter image description here

Example

An example of some animated cartoon scenes, most using the same technique as described above, can be found at https://vimeo.com/305374856

enter image description here

(the source code is available from https://github.com/samcarter/Extravanganza2018)

2

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.

nithardus
  • 21
  • 3