# Exporting a sequence of graphs as video efficiently

I have a sequence of graphs that are being created within Mathematica which I'm exporting to create an animated plot of the graph, as follows.

startTime = 0;
endTime = 5;
secondsPerFrame = 1/30;

sampleData = {#, #^3 - 5*#^2 + #} & /@ Range[startTime, endTime, secondsPerFrame];
{tList, xList} = sampleData\[Transpose];

timeInformationLocation = {0.2 + Min@tList, 0.9*Max@xList};
timeInformation =
Graphics[Text[
"Time: " <> ToString[NumberForm[N[#1], {10, 2}]] <> " s",
timeInformationLocation, {-1, 0}, BaseStyle -> {Black, 16}]] &;

evaluationInitialTime = AbsoluteTime[];

graphListForExport =
ParallelTable[
Show[ListPlot[Select[Transpose[{tList, xList}], #[[1]] < tdummy &],
PlotRange -> {1.1*{0, Max@tList}, 1.1*{Min@xList, Max@xList}},
AxesOrigin -> {0, 0}, AxesLabel -> {"time / s", "position / m"},
LabelStyle -> {Black, 16}, ImageSize -> 440,
PlotMarkers -> {Automatic, 6}],
timeInformation[tdummy]], {tdummy, startTime + secondsPerFrame,
endTime, secondsPerFrame}];
Print[Row[{"List of graphs completed at ", AbsoluteTime[] - evaluationInitialTime}]];

SetDirectory[NotebookDirectory[]];
Export["sample.mov", graphListForExport];

Print[Row[{"Export completed at ", AbsoluteTime[] - evaluationInitialTime}]];


Unfortunately, exporting the images is very slow; for the sample code above to export 150 frames, my system takes ~9s to generate the list of graphs, but another ~90s to export the list into the .mov format.

The question is, how can I optimize exporting a list of Graphics as a video?

There are several things which possibly could be done to improve the code. Firstly, when making the list of graphs, I could have chosen to use Graphics instead, which is likely to be faster. However, as most of the time seems to be taken up in the export step, I would like to focus on that first.

Since I would be processing the video in other software afterwards, I considered encoding the video in another format. However, while saving the video as .avi leads to some performance improvements (~60s for export versus ~90s), it is still rather slow. Other formats seem to be even slower than .mov, although I don't have the hard numbers for this specific example.

I also attempted to export the graphs immediately as a list of images that I could string together again via ffmpeg. Again, there was no significant performance improvement, and considering the additional work that has to be done to produce the final video, I'm not sure whether it is worth it.

Halirutan suggested in chat to rasterize the images first, and YvesKlett added to that by pointing out that the process of rasterization could in fact be parallelized. However, when I attempt to rasterize the images in my system my system crashed. The two approaches I used to try to rasterize the image were inserting a Rasterize within my ParallelTable and inserting the code graphListForExport=Rasterize\@graphListForExport.

For my final application, I will be exporting about 30s worth of graphs at 60fps, which means a total of 1800s. Each export takes about an hour, meaning that modifying elements in the video is very time-consuming.

I'm running Mathematica 9.0 on a system with a Dual Core 1.86 Ghz CPU, and 2.50 GB of RAM.

-
Did you adjust \$HistoryLength=0? That will help you RAM-wise. – Yves Klett Jun 27 '13 at 5:41
I've found some advantages to the ffmpeg method: you can fix errors/regenerate single frames, there's more control over output formats, if you get a powercut or a crash you can start again from where you left off, you can more easily monitor progress, and so on. But video is so processor-intensive anyway; just fire it up and go for lunch! (Some individual frames for Toy Story took 30 hours to render...) – cormullion Jun 27 '13 at 7:00
@YvesKlett nope, I didn't - and I should have! let me try again with that. – Vincent Tjeng Jun 27 '13 at 7:46
@VincentTjeng So far my record for generating a movie was 27 hours for about 5 minutes of output... :) – cormullion Jun 27 '13 at 7:53
@VincentTjeng "A watched export never completes" as my grandmother would have said... In hindsight I needn't have generated each frame at 6000 pixels resolution.:) – cormullion Jun 27 '13 at 8:18

Here's one thing that might ease the pain a little: calculate and save the images in the movie one by one, saving them all to a directory. Once done, read them all back in and export to the movie. The first step is something like:

Do[thisImg = (* define your images here *);
Export[path ~~ folder ~~ ToString[PaddedForm[r, {4, 2}]] ~~ ".jpg",
thisImg];, {r, 1, 500, 1}];


As jens points out, if you have already generated all the plots, you can simplify some of the book-keeping by using the VideoFrames option, which automatically labels the file names sequentially

Export["plot001.png", plots, "VideoFrames"];


Of course you might prefer to save to a .png file and you may need to Rasterize (depending on what your graphics are). Once all the individual frames are stored in one folder, you can read them all in and make the movie:

path = "/Users/Desktop/folderName/" ~~ folder ~~ "/";
fileNames = FileNames["*.jpg", path];
graphics = Table[Import[fileNames[[num]]], {num, 1, Length[fileNames]}];
Export["/Users/Desktop/" ~~ folder ~~ ".mov", graphics];


Dividing the process this way allows you to catch mistakes at intermediate points where they can be mor easily fixed.

-
For this purpose it's better to use the VideoFrames format. – Jens Jun 27 '13 at 17:58
Thanks for the answer, bill. Offhand, I would expect that re-importing the graphics as a video would introduce an additional overhead and make the process slower, although it is definitely better from the perspective of catching mistakes first at the intermediate points. Let me do some benchmarks when I have the time so I can share them here. – Vincent Tjeng Jun 28 '13 at 3:57
Have you tried it? If you clear the kernel before doing the import (to wipe out memory of the creation of the plots) you may be surprised. – bill s Jun 28 '13 at 16:33
@bills Sorry for the late reply - I missed this somehow. I will try the suggestion that you made, and hopefully post the benchmarks soon. – Vincent Tjeng Jul 5 '13 at 6:32