23
23
from matplotlib .externals import six
24
24
from matplotlib .externals .six .moves import xrange , zip
25
25
26
+ import os
26
27
import platform
27
28
import sys
28
29
import itertools
30
+ import base64
29
31
import contextlib
32
+ import tempfile
30
33
from matplotlib .cbook import iterable , is_string_like
31
34
from matplotlib .compat import subprocess
32
35
from matplotlib import verbose
@@ -383,7 +386,6 @@ def cleanup(self):
383
386
384
387
# Delete temporary files
385
388
if self .clear_temp :
386
- import os
387
389
verbose .report (
388
390
'MovieWriter: clearing temporary fnames=%s' %
389
391
str (self ._temp_names ),
@@ -885,6 +887,51 @@ def _end_redraw(self, evt):
885
887
self ._resize_id = self ._fig .canvas .mpl_connect ('resize_event' ,
886
888
self ._handle_resize )
887
889
890
+ def to_html5_video (self ):
891
+ r'''Returns animation as an HTML5 video tag.
892
+
893
+ This saves the animation as an h264 video, encoded in base64
894
+ directly into the HTML5 video tag. This respects the rc parameters
895
+ for the writer as well as the bitrate. This also makes use of the
896
+ ``interval`` to control the speed, and uses the ``repeat``
897
+ paramter to decide whether to loop.
898
+ '''
899
+ VIDEO_TAG = r'''<video {size} {options}>
900
+ <source type="video/mp4" src="data:video/mp4;base64,{video}">
901
+ Your browser does not support the video tag.
902
+ </video>'''
903
+ # Cache the the rendering of the video as HTML
904
+ if not hasattr (self , '_base64_video' ):
905
+ # First write the video to a tempfile. Set delete to False
906
+ # so we can re-open to read binary data.
907
+ with tempfile .NamedTemporaryFile (suffix = '.m4v' ,
908
+ delete = False ) as f :
909
+ # We create a writer manually so that we can get the
910
+ # appropriate size for the tag
911
+ Writer = writers [rcParams ['animation.writer' ]]
912
+ writer = Writer (codec = 'h264' ,
913
+ bitrate = rcParams ['animation.bitrate' ],
914
+ fps = 1000. / self ._interval )
915
+ self .save (f .name , writer = writer )
916
+
917
+ # Now open and base64 encode
918
+ with open (f .name , 'rb' ) as video :
919
+ vid64 = base64 .encodebytes (video .read ())
920
+ self ._base64_video = vid64 .decode ('ascii' )
921
+ self ._video_size = 'width="{0}" height="{1}"' .format (
922
+ * writer .frame_size )
923
+ os .remove (f .name ) # Now we can remove
924
+
925
+ # Default HTML5 options are to autoplay and to display video controls
926
+ options = ['controls' , 'autoplay' ]
927
+
928
+ # If we're set to repeat, make it loop
929
+ if self .repeat :
930
+ options .append ('loop' )
931
+ return VIDEO_TAG .format (video = self ._base64_video ,
932
+ size = self ._video_size ,
933
+ options = ' ' .join (options ))
934
+
888
935
889
936
class TimedAnimation (Animation ):
890
937
'''
0 commit comments