15

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

2 Answers 2

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)

1
  • 2
    Impressive... impressive... CRAZY!
    – Daniel
    Commented Dec 9, 2018 at 23:10
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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .