Last updated on June 14, 2017
This article describes how to produce MP4 and WebM video files compatible with Radiant Media Player and HTML5 video in general. For this guide with use the latest FFmpeg version available as of June 2017 (N-86442-g8aa6060) on Ubuntu Desktop LTS 16.04 64-bits.
General instruction for installing FFmpeg can be found here.
Guidelines for compiling FFmpeg can be found here.
Enabling some encoding/decoding options with FFmpeg can trigger licensing requirements depending on your use-case. Radiant Media Player does not provide licensing for encoding/decoding media content.
In this section we will review how to produce MP4 files that will work with HTML5 video on devices where H.264 video and AAC-LC audio are supported. Specifically we will produce keyframes aligned video files at different bitrates and resolutions. This is a requirement for proper adaptive bitrate streaming in DASH and HLS.
We use a 16:9 1920x1080 24fps (a.k.a. True HD 1080p24) MOV input video file named input.mov. If you need a sample to play around, can get one from blender.org site.
ffmpeg -i input.mov -s 640x360 -c:v libx264 -b:v 650k -r 24 -x264opts keyint=48:min-keyint=48:no-scenecut -profile:v main -preset fast -movflags +faststart -c:a libfdk_aac -b:a 128k -ac 2 out-low.mp4
-i input.mov: this is our input video file
-s 640x360: we tell FFmpeg to resize our input file to 640x360 while transcoding
-c:v libx264: we tell FFmpeg to use x264 as the video encoding library
-b:v 650k: the target video bitrate should be 650 kbps
-r 24: we want a constant framerate at 24 fps (which is the same as our source video file in this case)
-x264opts keyint=48:min-keyint=48:no-scenecut: we should have one keyframe every 48 frames (every 2 seconds). The keyframe injection should be constant
-profile:v main: we want H.264 main profile which is supported by most devices on the market while offering good transcoding quality and options
-preset fast: we use a fast preset for x264 transcoding
-movflags +faststart: the file should be web ready (moov box before mdat box)
-c:a libfdk_aac: we use libfdk_aac as our audio encoding library
-b:a 128k: the target audio bitrate should be 128 kbps
-ac 2: we want a stereo (2 audio channels) output
out-low.mp4: our output file should be a MP4 file named out-low.mp4
Once we have created our first rendition we can create others at different resolutions and bitrates.
ffmpeg -i input.mov -s 960x540 -c:v libx264 -b:v 1400k -r 24 -x264opts keyint=48:min-keyint=48:no-scenecut -profile:v main -preset fast -movflags +faststart -c:a libfdk_aac -b:a 128k -ac 2 out-med.mp4
ffmpeg -i input.mov -s 1280x720 -c:v libx264 -b:v 2500k -r 24 -x264opts keyint=48:min-keyint=48:no-scenecut -profile:v main -preset fast -movflags +faststart -c:a libfdk_aac -b:a 128k -ac 2 out-high.mp4
ffmpeg -i input.mov -s 1920x1080 -c:v libx264 -b:v 5500k -r 24 -x264opts keyint=48:min-keyint=48:no-scenecut -profile:v main -preset fast -movflags +faststart -c:a libfdk_aac -b:a 128k -ac 2 out-max.mp4
Here is a suggestive encoding table for H.264/AAC-LC (16:9 aspect ratio at 24fps up to 4K resolution) for adaptive bitrate streaming:
Generally a 0.1 bits/pixel ratio is good enough (but that may depend on content type) for H.264 encoding. A 0.11 bits/pixel ratio gives us a little more quality at an acceptable increase of video bitrate.
Now that you know about everything on H.264/AAC-LC encoding we can go ahead with H.265/HE-AACv2 encoding. H.265 claims it can reduce file size up to 50% versus H.264 without loss of quality (in reality H.265 works well at lower and higher bitrate but may not be as ground breaking as it wants to be especially considering the licensing cost). HE-AACv2 is a newer version of AAC which works well for low bitrate audio encoding.
ffmpeg -i input.mov -s 640x360 -c:v libx265 -b:v 390k -r 24 -x265-params "keyint=48:min-keyint=48:no-open-gop:no-scenecut" -preset fast -movflags +faststart -c:a libfdk_aac -profile:a aac_he_v2 -b:a 96k -ac 2 out-low.mp4
Here is a suggestive encoding table for H.265/HE-AACv2 (16:9 aspect ratio at 24fps up to 4K resolution) for adaptive bitrate streaming:
Generally a 0.07 bits/pixel ratio is an acceptable conservative ratio for H.265 encoding. You can go down to a 0.06 bits/pixel ratio for smaller bitrate.
A H.265 encoding guide is available here.
Alternatively to the patent-encumbered H.26*/AAC codecs we can use the open and royalty free VP9 video & opus audio codecs. VP9/opus work great on most modern browsers but with the significant caveat that macOS, iOS and most Microsoft browsers do not support them :(
Arguably VP9 (slightly) outperforms H.264 for video encoding. H.265 does outperform VP9 encoding however. The future release of the AV1 codec may just match H.265 current capabilities. In all cases, aside obvious licensing considerations for H.26* and AAC, adoption is going to be an issue. HEVC has slow adoption as of mid 2017 (though this may change with Apple announcing support for HEVC on iOS 11 and macOS High Sierra at WWDC 2017). We can bet that companies holding HEVC patents are going to be reluctant to sail with AV1 even if it becomes as good as HEVC ... to be continued.
But enough with the chit-chat and let us do some encoding:
ffmpeg -i input.mov -s 640x360 -c:v libvpx-vp9 -minrate 480k -maxrate 480k -b:v 480k -r 24 -c:a libopus -b:a 96k -ac 2 out-low.webm
A guide to VP9 encoding with FFmpeg is available here. In the above example we used a constant bitrate (CBR) encoding approach. I am a big fan of CBR (or more precisely CVBR - constrained variable
bitrate) encoding because as some of you may know UVBR (unconstrained variable bitrate) may cause issues at decoding time especially on lower end devices or in poor network conditions. Achieving CBR or CVBR with VP9 encoding is quite straight
forward - for H.264 it can be done but you are going to need to do some research about the
bufsize setting (help for H.264 CBR encoding can be found here).
Here is a suggestive encoding table for VP9/Opus (16:9 aspect ratio at 24fps up to 4K resolution) for adaptive bitrate streaming:
Generally a 0.85 bits/pixel ratio is an acceptable semi-conservative ratio for VP9 encoding.
For WebM with VP8 video and Vorbis audio the command line should look like:
ffmpeg -i input.mov -s 640x360 -c:v libvpx -minrate 650k -maxrate 650k -b:v 650k -r 24 -c:a libvorbis -b:a 192k -ac 2 out-low.webm
Generally a 0.11 bits/pixel ratio is an acceptable ratio for VP8 encoding (see H.264/AAC table above). Vorbis audio generally provides lesser quality than AAC or Opus especially at lower bitrate so make sure to give a little boost to audio bitrate when using Vorbis audio codec.