Embedding videos in Google Slides as GIFs
In my field, systems biology, it's pretty common to take time-lapse movies
to get the dynamics of how the system behaves. And we like showing them
off. This makes Google Slides[^1] inability to embed videos (without
uploading them to Youtube) pretty annoying and inconvenient. Slides does,
on the other hand, have good support for embedding GIFs. I came up with
the following pipeline (based on notedible's comment on
First, make sure to install
imagemagick. On Debian-based
systems, you can run
sudo apt-get install libav-tools imagemagick
and on MacOS[^2] the easiest way to install them is via homebrew. Then I use the following command to create the GIF:
cat some_movie.m4v | avconv -i pipe: -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -loop 0 - gif:- | convert -layers Optimize - output.gif
some_movie.m4v is the video file. This creates an optimized GIF
output.gif, which you can then upload to Google Slides.
The last niggle is that the GIFs play continuously and sometimes it's
helpful to be able to stop/start the playback. Enter the Toggle Animated
extension for Firefox (I'm sure there's something comparable for Chrome),
which lets you do just that.
If you get an error that looks like the following with some weirdly
avconv version 12, Copyright (c) 2000-2016 the Libav developers built on Mar 6 2017 22:35:59 with Apple LLVM version 8.0.0 (clang-800.0.42.1) [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fc78b000000] stream 0, offset 0x30: partial file [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fc78b000000] Could not find codec parameters (Video: mpeg4 (Simple Profile) [mp4v / 0x7634706D] none, 1958 kb/s) Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:': Metadata: major_brand : qt minor_version : 537199360 compatible_brands: qt creation_time : 2015-05-26 19:04:15 Duration: 00:00:10.00, bitrate: N/A Stream #0:0(eng): Video: mpeg4 (Simple Profile) [mp4v / 0x7634706D] none, 1958 kb/s 600 tbn (default) Metadata: creation_time : 2015-05-26 19:04:15 handler_name : Apple Alias Data Handler encoder : MPEG-4 Video Output #0, image2pipe, to 'pipe:': Output file #0 does not contain any stream convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/509. convert: no images defined `gif:-' @ error/convert.c/ConvertImageCommand/3254. convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/509. convert: no images defined `output.gif' @ error/convert.c/ConvertImageCommand/3254.
Then installing the
qtfaststart[^3] Python package via
pip install qtfaststart and then running
qtfaststart bad_movie.mov good_movie.mov
should fix the problem and now you can use
good_movie.mov with the
previous commands to create all the gifs. So
what is happening is that some recording software puts the
prior to the
moov block (the structural metadata). This is more
convenient for recording since the structure isn't known till the
recording is finished, however for playback it isn't as nice.
qtfaststart fixes this by swapping the two blocks:
$ qtfaststart -l bad_movie.mov ftyp (32 bytes) wide (8 bytes) mdat (2448358 bytes) moov (998 bytes)
qtfaststart -l good_movie.mov ftyp (32 bytes) moov (998 bytes) wide (8 bytes) mdat (2448358 bytes)
[^1]: I like Google Slides for a variety of reasons, but the main ones are its simplicity, portability, and collaboration features. Hard to beat for presentations.
[^2]: OS X dammit
[^3]: So apparently this Python package just repackages ffmpeg's own qtfaststart.c file. Why ffmpeg can't do this on its own? Who knows.