Videos: encode once play anywhere

Mike Dawson
3 min readApr 8, 2024

Videos encoded using AV1 can be around half the size of H264 whilst providing an equivalent quality. I’ve found that as little as 250kbps can be enough for educational videos to be suitable for use on a laptop screen. Meta Engineering’s tests concluded that AV1 beats H264 and VP9. AV1 files can provide similar quality to H264 at around half the size.

There is a minefield of video encoding options that each has advantages and limitations. Some larger sites may encode a video in multiple formats and bandwidth settings. In many cases (e.g. offline download/resharing) it’s much easier if one format that is good enough for all use cases can be identified.

Video codec options:

  • H264 : H264 has the widest compatibility, unfortunately, it doesn’t deliver the quality for bandwidth that can be delivered by newer codecs. It’s quick to encode.
  • H265 : H265 is supported on Android since Android 5. Most Android devices support encoding H265 (including via the Media3 transcoder). It delivers much better (not quite as good as AV1) quality for bandwidth. It is not supported by Firefox by default. It also only works on Chrome (and derivatives) where there is underlying hardware support (does not work out of the box on my Ubuntu machine). The limited support on browsers and Linux is the result of license/patent (not technical) issues.
  • VP9 : VP9 playback is supported since Android 4.4. Jetpack media3 transcoder can’t encode VP9 because it only supports MP4 container files (and VP8/VP9 requires a webm container and cannot be contained in an MP4 file). VP9 has no licensing or patent issues and playback works fine on all recent browsers.
  • AV1 : AV1 decoding is supported since Android 10 (as of October 2023, that would leave approx 24% of Android devices without builtin AV1 support). This can be worked around by using ExoPlayer’s av1 decoder module that provides fallback software support to Android5+ (adds 2.8MB to the APK size). AV1 hardware accelerated encoding is required for all Android 14+ devices, but not all Android devices can support it. Playback works fine on all recent browsers and there are no licensing or patent issues.

Transcoders:

  • On Android: The Jetpack Media3 Transcoder is by far the least painful option. Encoding can fail on one device with a given resolution/bitrate etc and succeed on another device running the same version of Android due to hardware differences. Other options like Litr leave these problems to the developer.
  • On desktop/server: VLC’s transcoder is buggy. I generated MP4s that would play fine in Chrome, however would skip the first 30 seconds of video (not audio) when played using VLC itself. Handbrake “just works”, and comes in at just 20MB (e.g. if embedded), far less than the 170MB ffmpeg zip size.

Recommendation:

AV1 is what has momentum. The primary drawback of using AV1 is the requirement to bundle the encoder for ExoPlayer to support pre-Android 10 devices. Given that AV1 isn’t encumbered by patent and licensing issues, it is a mystery as to why Google is insisting that developers need to compile and build the ExoPlayer AV1 module themselves.

“Normal” users definitely don’t want to have to deal with this complexity, so the Ustad Mobile app provides five presets which use the following handbrake parameters:

  • Highest (roughly 1MB per min of video) : quality =55, max resolution = 480x360, audio bit rate = 32kbps, frame rate = 15
  • High (roughly 2MB per min of video) : quality = 55, max resolution = 480x360, audio bit rate = 48kbps, frame rate = 30
  • Medium (roughly 3MB per min of video) : quality = 55, max resolution = 720x480, audio bit rate = 96kbps, frame rate = 30
  • Low (roughly 5MB per min of video) : quality = 45, max resolution = 720x480, audio bit rate= 128kbps, frame rate = 30
  • Lowest (roughly 11–12MB per minute of video), max resolution = 1280x720, audio bit rate = 196kbps, frame rate = 30

Using the quality control setting the quality should remain relatively constant, the bit rate and file size will vary depending on the complexity of the video.

--

--