Skip to content

Instantly share code, notes, and snippets.

@leepeterson
Forked from Vestride/encoding-video.md
Last active February 19, 2020 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save leepeterson/8a25ae10dbd0b3a7215b1ae0c5728b75 to your computer and use it in GitHub Desktop.
Save leepeterson/8a25ae10dbd0b3a7215b1ae0c5728b75 to your computer and use it in GitHub Desktop.
Rawle Murdy's Web Video Requirements

Rawle Murdy's Web Video Requirements

As of July 2018:

  1. 4K WebM video encoded with VP9

2a. 1080p MP4 video encoded with HEVC/H.265

2b. Optional: 1080p MP4 encoded with MPEG-4/H.264 (if Windows Mobile and IE8-11 support is required)

ffmpeg Examples

  • Given a 250MB 1080p MP4, render an h264 MP4 with AAC audio with final size of 5.5MB playing at 1500Kb/s; allow the video to begin playing before it is completely downloaded by the viewer by passing -movflags +faststart
    • brew install ffmpeg --with-libvpx --with-libvorbis --with-fdk-aac --with-opus
    • ffmpeg -i source.mp4 -c:v h264 -c:a aac -b:v 1500k -threads 4 -movflags +faststart out.mp4
  • ffmpeg -i source.mp4 -c:v h264 -b:v 1500k -vf scale=1280:-1 -threads 4 -an out.mp4
    • Install brew install ffmpeg with the flags --with-libvpx --with-libvorbis set
    • Installation time on a 4-core Skylake with 8GB RAM: ~20 minutes
    • Example output: given a 450MB 4K MP4, rendered output is a 6MB MP4 with no audio, suitable for video heroes
    • Encoding time required: ~4 minutes
  • ffmpeg -i <source> -c:v libvpx-vp9 -pass 1 -b:v 1000K -threads 8 -speed 4 -tile-columns 6 -frame-parallel 1 -an -f webm /dev/null && ffmpeg -i <source> -c:v libvpx-vp9 -pass 2 -b:v 1000K -threads 8 -speed 1 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 -c:a libopus -b:a 64k -f webm out.webm
  • ffmpeg -i source.mp4 -c:v h264 -b:v 1000k -vf scale=1280:-1 -filter:v "fade=in:st=0:d=1, fade=out:st=9:d=1" -threads 4 -an out.mp4

Installing

macOS 10.13 High Sierra

ffmpeg's installation guide has more information if needed, but the following should be all you need.

Install FFmpeg with homebrew. You'll need to install it with a couple flags for webm and the AAC audio codec.

brew install ffmpeg --with-libvpx --with-libvorbis --with-fdk-aac --with-opus

fdk-aac and opus are required for audio. You may omit them if audio is not desired.

If you want a nice set of codecs and tools for post-rendering tasks:

brew install ffmpeg --with-fdk-aac --with-tools --with-freetype --with-libass --with-libvorbis --with-libvpx --with-x265

If you want everything ffmpeg has to offer, run:

brew install ffmpeg $(brew options ffmpeg | grep -vE '\s' | grep -- '--with-' | tr '\n' ' ')

If you want everything, and if you enjoy making your life difficult, run:

brew install ffmpeg --with-chromaprint --with-fdk-aac --with-fontconfig --with-freetype --with-frei0r --with-game-music-emu --with-libass --with-libbluray --with-libbs2b --with-libcaca --with-libgsm --with-libmodplug --with-librsvg --with-libsoxr --with-libssh --with-libvidstab --with-libvorbis --with-libvpx --with-opencore-amr --with-openh264 --with-openjpeg --with-openssl --with-opus --with-rtmpdump --with-rubberband --with-sdl2 --with-snappy --with-speex --with-tesseract --with-theora --with-tools --with-two-lame --with-wavpack --with-webp --with-x265 --with-xz --with-zeromq --with-zimg

If you already have ffmpeg installed, but not with the audio codecs, use the reinstall command.

brew reinstall ffmpeg --with-opus --with-fdk-aac

Note: Java 1.8+ is required to install this formula; Java can be installed with brew cask install java (recommended), or by downloading and installing it yourself.

FFmpeg options. The -c:v option is an alias for -vcodec and -c:a is an alias for -acodec. -crf is Constant Rate Factor.

Linux

Refer to ffmpeg's compilation guide for Ubuntu, Debian, or Mint.

In your home directory make a new directory to put all of the source code and binaries into:

mkdir -p ~/ffmpeg_sources ~/bin

From that new directory, run:

sudo apt-get update -qq && sudo apt-get -y install autoconf automake build-essential cmake git-core libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libx264-dev libx265-dev libnuma-dev libvpx-dev libfdk-aac-dev libopus-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev

Windows 10

Refer to ffmpeg's compilation guide for Windows 10.

Convert to MP4

When converting to an MP4, keep in mind that Windows Mobile and IE8-11 only support the h264 video and aac audio codecs. If these browsers aren't required, or if videos rendered specifically for Windows Mobile and IE8-11 is a goal, then definitely choose the HEVC/H.265 video codec with aac or mp3 audio codec for maximum compatibility.

Edge 12 supports HEVC/H.265, but it also partially supports VP9. It is suggested that you try various combinations given these facts to see what works best for your video file.

The FFmpeg and H.264 Encoding Guide can walk also you through some of the H.264 specific options.

ffmpeg -i input.mov -vcodec h264 -acodec aac -strict -2 output.mp4

For maximum compatibility, use the profile option. This may, however, increase the bit rate quite a bit. You can disable the audio stream with the -an option. -pix_fmt yuv420p is for Apple Quicktime support.

In this example, input.mov is converted to output.mp4 with maximum compatibility, with Quicktime support, and without an audio stream.

ffmpeg -an -i input.mov -vcodec libx264 -pix_fmt yuv420p -profile:v baseline -level 3 output.mp4

Convert to WebM

VP8

libvpx is the VP8 video encoder for ​WebM. FFmpeg and WebM Encoding Guide will walk you through webm specifics.

In this example, input.mov is converted to output.webm with a constant rate factor of 10 (lower is higher quality) at a bitrate of 1M. Changing the bitrate to something lower (e.g. 700K) will result in lower file sizes and lower quality. If the video does not have audio (or if you do not need audio), omit -acodec libvorbis.

ffmpeg -i input.mov -vcodec libvpx -qmin 0 -qmax 50 -crf 10 -b:v 1M -acodec libvorbis output.webm

VP9

VP9 can encode videos at half the file size. You can check out Google's VP9 encoding guide for their recommend settings or the FFmpeg VP9 guide.

Here's an example from the FFmpeg guide:

ffmpeg -i input.mov -vcodec libvpx-vp9 -b:v 1M -acodec libvorbis output.webm

And here's Google's "Best Quality (Slowest) Recommended Settings". Run the first line, ignore the resulting warning (that the out.webm is empty; it was output to /dev/null), then run the second line. The video will be output as out.webm.

ffmpeg -i <source> -c:v libvpx-vp9 -pass 1 -b:v 1000K -threads 1 -speed 4 -tile-columns 0 -frame-parallel 0 -auto-alt-ref 1 -lag-in-frames 25 -g 9999 -aq-mode 0 -an -f webm /dev/null

ffmpeg -i <source> -c:v libvpx-vp9 -pass 2 -b:v 1000K -threads 1 -speed 0 -tile-columns 0 -frame-parallel 0 -auto-alt-ref 1 -lag-in-frames 25 -g 9999 -aq-mode 0 -c:a libopus -b:a 64k -f webm out.webm

Support

As of January 2015, all major browsers support MP4. Since all browsers support MP4, we can use WebM's VP9 codec for modern browsers and fall back to MP4s for the rest.

Data current as of July 2018. Sources:

Browser H264 H265 VP8 VP9 AAC MP3 VORBIS OPUS
Chrome for Desktop 30 - 30 30 30 30 30 33
Chrome for Android 30 - 30 30 30 30 30 -
IE 9 101 - - 9 9 - -
IE Mobile 10 - - - 10 10 - -
Edge 12 121 - 142 12 12 - 14
Firefox for Desktop 22 - 20 28 22 22 20 20
Firefox for Android 20 - 20 28 20 20 20 20
Safari for Mac 3 113 - - 3 3 - -
Safari for iOS 3 113 - - 3 3 - -
Opera for Desktop 25 - 11 16 - - 11 12
Android Stock Browser 2.3 - 4.0 5 2.3 2.3 4.0 -
----------------------- ------ ---------------- ----- ---------------- ----- ----- -------- ------
  1. Supported only for devices with hardware support.
  2. Edge 14+ has partial support for VP9
  3. Supported only on macOS High Sierra.

Notes

Constant Rate Factor

This method allows the encoder to attempt to achieve a certain output quality for the whole file when output file size is of less importance. This provides maximum compression efficiency with a single pass. Each frame gets the bitrate it needs to keep the requested quality level. The downside is that you can't tell it to get a specific filesize or not go over a specific size or bitrate.

Resources

WebM

MP4

HTML markup

Since all browsers support MP4, we can use WebM's VP9 codec for modern browsers and fall back to MP4s for the rest.

<video>
  <source src="path/to/video.webm" type="video/webm; codecs=vp9,vorbis">
  <source src="path/to/video.mp4" type="video/mp4">
</video>

Thumbnails

The ffmpeg thumbnail guide describes how to output a single frame from the video.

ffmpeg -i input.mp4 -ss 00:00:14.435 -vframes 1 out.png

Output one image every second as a jpg.

ffmpeg -i input.mp4 -vf fps=1 out%3d.jpg

Reversing a video

FFmpeg now has a reverse filter. Usage: (source from this video.stackexchange answer)

For video only:

ffmpeg -i input.mp4 -vf reverse reversed.mp4

For audio and video:

ffmpeg -i input.mp4 -vf reverse -af areverse reversed.mp4

This filter buffers the entire clip. For larger files, segment the file, reverse each segment and then concat the reversed segments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment