This notebook first appeared as a blog post on Pythonic Perambulations.
License: BSD (C) 2013, Jake Vanderplas. Feel free to use, distribute, and modify with the above attribution.
As usual, we'll start by enabling the pylab inline mode to make the notebook play well with matplotlib.
In [1]:
%pylab inline
Now we'll create a function that will save an animation and embed it in an html string. Note that this will require ffmpeg or mencoder to be installed on your system. For reasons entirely beyond my limited understanding of video encoding details, this also requires using the libx264 encoding for the resulting mp4 to be properly embedded into HTML5.
In [2]:
from tempfile import NamedTemporaryFile
VIDEO_TAG = """<video controls>
<source src="data:video/x-m4v;base64,{0}" type="video/mp4">
Your browser does not support the video tag.
</video>"""
def anim_to_html(anim):
if not hasattr(anim, '_encoded_video'):
with NamedTemporaryFile(suffix='.mp4') as f:
anim.save(f.name, fps=20, extra_args=['-vcodec', 'libx264'])
video = open(f.name, "rb").read()
anim._encoded_video = video.encode("base64")
return VIDEO_TAG.format(anim._encoded_video)
With this HTML function in place, we can use IPython's HTML display tools to create a function which will show the video inline:
In [3]:
from IPython.display import HTML
def display_animation(anim):
plt.close(anim._fig)
return HTML(anim_to_html(anim))
The result looks something like this -- we'll use a basic animation example taken from my earlier Matplotlib Animation Tutorial post:
In [4]:
from matplotlib import animation
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)
# initialization function: plot the background of each frame
def init():
line.set_data([], [])
return line,
# animation function. This is called sequentially
def animate(i):
x = np.linspace(0, 2, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
# call our new function to display the animation
display_animation(anim)
We can go a step further and use IPython's display hooks to automatically
represent animation objects with the correct HTML. We'll simply set the
_repr_html_
member of the animation base class to our HTML converter
function:
In [5]:
animation.Animation._repr_html_ = anim_to_html
Now simply creating an animation will lead to it being automatically embedded in the notebook, without any further function calls:
In [6]:
animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
Out[6]:
So simple! I hope you'll find this little hack useful!