Who said GIFs are cool? …oh, did I? Nevermind.
[There is no tl;dr here peeps, sorry — you’ll have to go through my ramblings]
In the last article, I showed you how to create a GIF out of a video capture of your app.
But let’s be honest, GIFs suck badly for this use case. Yes, yes, I know they’re basically the best thing ever for a lot of other occasions, including but not limited to: cute kittens and puppies clips, fail clips, Archer clips, reaction clips, and #pixelpushing posts.
But not for this. There is a simple reason why you can’t just drop the MP4 files that you get out of your device somewhere on the Internet and let them spread their own awesomeness.
Some websites don’t support proper video playback, but they do support animated GIFs just fine. Which ones? Well, for one, Medium. Then there’s our beloved GitHub. Oh, and most social networks. And some other websites. To these websites I have to say:
Hey lovely people over at Medium, and GitHub,
and all these other kewl websites I happen to use,
could you please please please do something about this?
Kthxbye.
Since I am not holding my breath over this, I want to share a couple of tips and general considerations you might find interesting.
On the GIF format
The GIF (supposedly pronounced jif, but I refuse to, as it’s too lame) format originated back in the late 80s at Compuserve. Now, back in the day people didn’t just lack good taste, they also happened to lack something we’re having abundance of nowadays: memory, processing power and bandwidth.
To cope with that, the GIF format only allows a finite palette of up to 256 colours, each being a 24-bit RGB entry indexed in a table in the header. This allows for smaller files when compared to 24 bpp bitmaps, which is good, but it’s at the same time really limiting for anything that is vaguely complex.
You can have dithering to partly compensate the lack of colour information, but that only helps up to a point, and it just looks terrible on uniformly-coloured areas (hello, Material Design!).
The creators of GIF also had the good idea of adding some form of (lossless) compression, and in particular, using the LZW algorithm, to save even more bandwidth. Which is all nice and fun, until you realise that even compared to the lousiest of modern compression algorithm, LZW is quite inefficient.
A real case against GIFs
We recently published a post on Novoda’s blog, that showcases some of the nice Material Design changes in one of our apps.
We have two animations there. We needed to show the new user interaction scenarios, and those sweet ripples. Let’s just focus on the first one.
The original screengrab from the Nexus 5 was a 1080 x 1920 px, 30 fps, 24bpp MP4 file. This comes straight from adb shell screenrecord, with an admittedly low bitrate for this resolution and framerate. This is what MediaInfo tells us about it:
Key fact: this full HD MP4 video is 4,977,749 bytes.
We decided to use GIFs on the blog, at first. How much would a 400 px wide GIF at 15 fps weight? Well…
Exactly 4,743,102 bytes. Which is 95% of the original video. At half the framerate, a third of the colour depth, and a fraction of the resolution. A way better quality MP4 will typically be 50–60% of the best GIF you can get.
Ok, GIF sucks. What now?
Well, as it turns out, you have two alternatives, and both involve proper video formats.
HTML5 to the rescue
You might have heard of this nifty little thing called HTML5 that has recently been finalised as a standard. In there, you will find the extremely convenient <video> tag that — guess what! — plays a video file.
You can simply drop your MP4 files in a video tag and call it a day:
<video loop autoplay>
<source src="materialyolo.mp4" type="video/mp4">
</video>
This has two issues, though. The first is that the video will most likely be too big (1080 x 1920 is a pretty huge resolution!), and the second is that some browsers won’t show any video.
For the first issue, you could scale the video by just adding some width and height attributes to the tag:
<video loop autoplay width=300 height=532>
<source src="materialyolo.mp4" type="video/mp4">
</video>
But this will look fugly, as browsers are quite bad at scaling stuff. You should rather reencode your source MP4 file into a smaller resolution — this way you will also save some more bandwidth. Here’s how, using our friend ffmpeg:
ffmpeg -i materialyolo.mp4 -vf scale=300:532 materialyolo-small.mp4
As per the second issue, this is happening because some browsers like Firefox don’t support the MP4/H.264 file format. You can work around this by specifying an alternative source in the video tag:
<video loop autoplay>
<source src="materialyolo-small.mp4" type="video/mp4">
<source src="materialyolo-small.webm" type="video/webm">
</video>
The open source WEBM format is supported in Firefox and other browsers, so you should be ok with that in. But it’s a bit of a pain to get ffmpeg to create webm files. You first need to rebuild ffmpeg with the necessary support for it. For example, on a Mac, using Homebrew:
brew reinstall ffmpeg --with-libvpx
You can then merrily issue the conversion command:
ffmpeg -i materialyolo.mp4 -c:v libvpx -pix_fmt yuv420p -b:v 2M \
-crf 5 -vf scale=300:-1 materialyolo-small.webm
Ta-dah!
As an aside, WEBM files also work on Google+ the same way GIFs do. Yay!
YouTube all the things!
This is in some cases (erm… Medium?) the only viable solution. It’s dead easy, just head over to YouTube and upload your videos, then use the embed links to incorporate the videos where you want.
The drawbacks are that you don’t really have control over the playback (can’t autoplay, can’t loop, can’t hide the controls) nor over the aesthetics of the player. Here’s an example of YouTube’s embed capabilities:
Less than stellar, right?
In which we say goodbye
What did we learn?
- GIFs are awesome, except when they aren’t
- HTML5 video is awesome, except when it doesn’t work
- YouTube embeds are awesome, except they aren’t, really
I hope this will help you make the most of each situation, using the best tool available at any time. Personally, I’d go for this order: MP4/WEBM, GIF, YouTube embed.