Closed billbrod closed 4 months ago
I think, broadly, there are two possible solutions here:
plt.rcParams['animation.html']
to 'jshtml'
, then the matplotlib animation object will be displayed automatically (no call to convert_anim_to_html
required), without using ffmpeg (essentially, this bypasses the selection in rcParams['animation.writer']
). (Note that setting this to 'html5'
also removes the necessity to call convert_anim_to_html
, but still uses ffmpeg)rcParams['animation.ffmpeg_args'] = ['-threads', '1']
, which forces ffmpeg to be single-threadedWhen using 'jshtml'
, I also need to raise plt.rcParams['animation.embed_limit']
in order to render the whole animation. Even in cases where the animation that ffmpeg would save out is very small. e.g.,
mdl = po.simul.Gaussian(7)
po.tools.remove_grad(mdl)
mdl.eval()
img = po.data.einstein()
met = po.synth.Metamer(img, mdl)
met.synthesize(100, store_progress=True)
then
plt.rcParams['animation.html'] = 'jshtml'
po.synth.metamer.animate(met)
needs an embed limit of between 40 and 50 MB, whereas
plt.rcParams['animation.writer'] = 'ffmpeg'
anim=po.synth.metamer.animate(met)
anim.save('test.mp4')
creates a 320K video. presumably because ffmpeg can use the h264 codec and the javascript writer can't?
Because of that and the fact that jshtml seems to be slower than ffmpeg, it might be worth just telling ffmpeg to use a single thread (even though ffmpeg is an additional installation).
Basically:
conda update ffmpeg
) po.tools.display.convert_anim_to_html
rcParams['animation.writer']
Okay, I think the embed issue is pretty serious (users could easily have a huge uncompressed video as the output of our animation methods), so I'm going to stick with ffmpeg, but force a single thread and set rcParams['animation.html']
, which will allow me to get rid of the convert_anim_to_html
helper function.
To finish this up, the following should be added to the top of every notebook that creates an animation:
plt.rcParams['animation.html'] = 'html5'
# use single-threaded ffmpeg for animation writer
plt.rcParams['animation.writer'] = 'ffmpeg'
plt.rcParams['animation.ffmpeg_args'] = ['-threads', '1']
This is especially important for binders used during workshops, but not a bad idea to put on our docs examples as well
We can then also remove the convert_anim_to_html
function as well.
When using ffmpeg
as the animation writer, ffmpeg is required both for saving and displaying in notebooks. Previously, I had thought it was only required for saving the movie.
ffmpeg (which gets used as the backend for the matplotlib animation functions we use) appears to be trying to grab all the threads available, at least on the Flatiron Binderhub. This is bad when there are multiple people using the binderhub, and slows everything to a crawl.
Figure out either how to reduce the number of threads it uses (through matplotlib's interface), or switch to a different animation backend. since we're in a jupyter notebook, some javascript might be better.