# How to save animation in mp4 format instead of avi?

I'd like to save Manipulate[] output so that I can embed an mp4 in my pdf document (using the media9 latex package). I've done this successfully in the past by manually constructing a table of Graphics objects, and then saving that to .avi format. That .avi can then be converted to .mp4 by ffmpeg.

A cleaner way to do this is pointed out in this answer but the .avi file that is generated causes ffmpeg to choke:

Output #0, mp4, to 'MyAutorun.mp4':
Stream #0:0: Video: h264, yuv420p, 412x345, q=-1--1, 90k tbn, 15 tbc
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo -> libx264)
Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as     bit_rate, rate, width or height


I'm not really sure what this tool is complaining about, but wondered if there was a way to avoid using external tools to do this conversion and just export the animation data in mp4 format directly from Mathematica?

-
Couldn't you instead just export the Manipulate to swf format? The media9 package can handle that. The predecessor movie15 did that nicely, too - see my example page –  Jens Apr 14 '12 at 6:39
I suspect the encoder is complaining about the frame height being an odd number (345 pixels) –  Simon Woods Apr 14 '12 at 12:07
Simon, any idea how to make Mathematica use a non-odd numbered frame height? –  Peeter Joot Apr 14 '12 at 17:31
Peeter, the exported avi has the same dimensions as the Manipulate object, so you could use the option ImageMargins in the Manipulate, but the simpler approach is probably to set the frame size in ffmpeg as shown in Jens' answer. –  Simon Woods Apr 15 '12 at 18:45
Jens showed below how to use the -s option of ffmpeg to work around the size issue. I also tried adding ImageMargins -> 100 to my manipulate, but this didn't appear to force an even size to the generated Export[] output (and I still had to use ffmpeg -s) –  Peeter Joot Apr 17 '12 at 11:53

Edit 2

Strictly speaking, the answer to the question "How to save animation in mp4 format" is simply this:

Export["MyAutorun3.mov", m, "VideoEncoding" -> "MPEG-4 Video"]


I'm adding this for completeness. The .mov file contains an MPEG-4 encoded video, whereas the default with Mathematica is Cinepak. The reason why we have to jump through additional hoops is that this output file doesn't appear to work with the flash-based video players that ship with media9.

Edited: use Quicktime Player instead of ffmpeg

On Mac OS X, there's an easier alternative to ffmpeg to create a movie that works with media9. It requires no additional software.

First use the example from this post

m=Manipulate[Plot[Sin[a x + b], {x, -3, 3}], {a, 1, 10}, {b, -3, 3}]


Export as Quicktime, as F'x also suggested:

Export["MyAutorun.mov", m]


Open this movie in Quicktime Player (built-in on Mac) and choose File > Export ... with format 480p. The newly created movie (let's call it MyAutorun2.mov) can be incorporated in your $\LaTeX$ file, as in this example:

\documentclass{article}
\usepackage[english]{babel}
\usepackage{media9}

\begin{document}

\includemedia[
activate=pageopen,
width=200pt,height=170pt,
flashvars={%
src=MyAutorun2.mov
&scaleMode=stretch}
]{}{StrobeMediaPlayback.swf}
\end{document}


You could also export the Manipulate as SWF,

Export["MyAutorun.swf", m]


Flash seems to do everything mp4 would do in your case: it's small and can be embedded in PDF for Adobe Reader using the movie15 or media9 packages.

To understand possible errors you may be seeing, I'll be more specific in describing what works for me:

Now create a $\TeX$ file with the contents

\documentclass{article}
\usepackage{media9}
\usepackage[english]{babel}

\begin{document}
\includemedia[
activate=pageopen,
width=393pt,height=334pt
]{}{MyAutorun.swf}
\end{document}


The result displays and runs for me in Adobe Reader X 10.1.2 on Mac OS X Lion. I think swf is the easiest way to get movies from Mathematica to PDF. Everything else requires some detour.

The disadvantage of directly embedding Mathematica's SWF export into the PDF is that there are no actually useable playback controls. For that, the video player solution is needed. So here is how that works for me:

With an exported 'mov, run the following:

ffmpeg -i MyAutorun.mov -s 540x360 -vcodec libx264 MyAutorun.mp4


What I added here is an explicitly even pair of numbers as the frame size, and the codec info. Hopefully, this will help prevent the errors you're seeing.

Finally, I embed the resulting mp4 file with this $\LaTeX$ source:

\documentclass{article}
\usepackage[english]{babel}
\usepackage{media9}

\begin{document}

\includemedia[
activate=pageopen,
width=200pt,height=170pt,
flashvars={%
src=MyAutoRun.mp4
&scaleMode=stretch}
]{}{StrobeMediaPlayback.swf}
\end{document}


I didn't worry about reproducing the aspect ratio of the movie correctly here. The main thing is of course that your ffmpeg sizes should be big enough to avoid a blurry image for the desired player width. This worked for me.

-
If I try .swf then viewer produces the following error in the pdf file when I try to view it: "Argument Error - Invalid Parameter passed to method. TypeError - Error #1009: Cannot access a property of method of a null object reference." Note that I'm using StrobeMediaPlayer as recommended by the media9 maintainer: tex.stackexchange.com/questions/45242/… Using flv works better, but a second view attempt produces a "Buffering" status indicator that never goes away (I don't see that with an .mp4 format). –  Peeter Joot Apr 14 '12 at 14:33
I added what works for me, using SWF directly because with mp4 you'd have to load a SWF video player anyway which then displays your movie, which seems convoluted when you have the choice to avoid mp4 as your export format in Mathematica. But if you want to create mp4, another thing you could try is to export with Export["MyAutorun001", m, "VideoFrames"] and assemble the resulting TIFF files with the command convert -quality 100 MyAutorun???.tiff myAutorun.mp4. This requires ImageMagick (e.g. from MacPorts or Fink). –  Jens Apr 14 '12 at 18:50
The convert utility also lets you rescale the frames (if it turns out odd pixel height is an issue for you). –  Jens Apr 14 '12 at 18:52
the -s argument for ffmpeg works. I'd tried -srch, -srcw, but looking at the ffmpeg help, I think those may be for something else. –  Peeter Joot Apr 17 '12 at 14:17
Using your info, I've coded a small script to do this conversion, retrying if the size is odd: github.com/peeterjoot/physicsplay/blob/master/bin/convertToMp4 –  Peeter Joot Apr 17 '12 at 14:19

Exporting a QuickTime file (.mov extension) from Mathematica and then converting it into an MP4 file with ffmpeg does the trick for me:

Export["toto.mov", p];
Run["ffmpeg -i toto.mov -vcodec copy -acodec copy toto.mp4"];
Run["rm toto.mov"];


It works with both ffmpeg version I have installed (an old CVS version dated sometime in 2004, and a CVS version dated 2009-04-12), and with Mathematica 8 on Mac OS X.

-
What version of Mathematica are you using. If I try this I get an error: Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'twoCylindersFig3.mov': Duration: 00:00:08.00, start: 0.000000, bitrate: 583 kb/s Stream #0:0(eng): Video: cinepak (cvid / 0x64697663), yuv420p, 409x299, 581 kb/s, 15 fps, 15 tbr, 600 tbn, 600 tbc ...[mp4 @ 000000000036ED80] track 0: could not find tag, codec not currently supported in container –  Peeter Joot Apr 14 '12 at 14:23
@PeeterJoot Mathematic 8 on Mac OS X; edited my answer to include that –  F'x Apr 14 '12 at 15:19

The mp4 video to be generated must have even number of pixels in both dimensions. To ensure this independently from the input file, ffmpeg can be invoked as

ffmpeg -i in.avi -vf scale="trunc(iw/2)*2:trunc(ih/2)*2" -vcodec libx264 -x264opts keyint=25 out.mp4


-x264opts keyint=25` ensures that keyframes be inserted at every second. This is necessary for precise seeking within the video (using the <- / -> arrow keys of the keyboard [VPlayer.swf] or the slider [StrobeMediaPlayback.swf])

-
Thanks for detailing the magic required. –  Peeter Joot Oct 12 '12 at 16:43