Saving and displaying movies and dynamic figures

It is insanely useful to create movies to illustrate a talk, blog post or just to include in a notebook:

In [1]:
from IPython.display import HTML
HTML('<center><video controls autoplay loop src="../files/2016-11-15_noise.mp4" width=61.8%/></center>')
Out[1]:

For years I have used a custom made solution made around saving single frames and then calling ffmpeg to save that files to a movie file. That function (called anim_save had to be maintained accross different libraries to reflect new needs (going to WEBM and MP4 formats for instance). That made the code longer than necessary and had not its place in a scientific library.

Here, I show how to use the animation library from matplotlib to replace that

There quite a few pages on the web describing a possible alternative:

In [2]:
import numpy as np
image = np.random.rand(64, 16, 128)
from IPython.display import display, clear_output, HTML, Image
In [3]:
import sys
import matplotlib.pyplot as plt
from matplotlib import animation, rc
animation.rcParams['animation.writer'] = 'ffmpeg'

# First set up the figure, the axis, and the plot element we want to animate
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 2))
plt.close()
ax.xlim = (0, image.shape[1])
ax.ylim = (0, image.shape[2])
ax.set_xticks([])
ax.set_yticks([])
img = ax.imshow(image[:, :, 0].T, cmap='gray')
img.set_interpolation('nearest')
def animate(i): 
    #img = ax.imshow(image[:, :, i].T, cmap='gray')
    img.set_data(image[:, :, i].T)
    #ax.xaxis.set_visible(False)
    #ax.yaxis.set_visible(False)
    clear_output(wait=True)
    print ('It: %i'%i)
    sys.stdout.flush()
    return (img,)
            
# call the animator. blit=True means only re-draw the parts that have changed.
# *interval* draws a new frame every *interval* milliseconds.
anim = animation.FuncAnimation(fig, animate, frames=image.shape[-1], interval=50, blit=True)
HTML(anim.to_html5_video()) 
It: 127
Out[3]:

The same anim object can be used to save the movie as a file:

In [4]:
help(anim.save)
Help on method save in module matplotlib.animation:

save(filename, writer=None, fps=None, dpi=None, codec=None, bitrate=None, extra_args=None, metadata=None, extra_anim=None, savefig_kwargs=None) method of matplotlib.animation.FuncAnimation instance
    Saves a movie file by drawing every frame.
    
    *filename* is the output filename, e.g., :file:`mymovie.mp4`
    
    *writer* is either an instance of :class:`MovieWriter` or a string
    key that identifies a class to use, such as 'ffmpeg' or 'mencoder'.
    If nothing is passed, the value of the rcparam `animation.writer` is
    used.
    
    *dpi* controls the dots per inch for the movie frames. This combined
    with the figure's size in inches controls the size of the movie.
    
    *savefig_kwargs* is a dictionary containing keyword arguments to be
    passed on to the 'savefig' command which is called repeatedly to save
    the individual frames. This can be used to set tight bounding boxes,
    for example.
    
    *extra_anim* is a list of additional `Animation` objects that should
    be included in the saved movie file. These need to be from the same