Bulk compress videos to H.265 (x265) with ffmpeg
Apr 21, 2020
Despite being a relatively modern phone, my OnePlus 6T records video using the H.264 codec rather than the newer H.265 HEVC codec. A minute of 1080p video takes up ~150MB of storage, and double that for 60fps mode or 4K. Even though the phone has a decent amount of storage (64GB) it quickly fills up if you record a lot of video.
The storage savings from HEVC are pretty astounding. It typically requires 50% less bitrate (and hence storage space) to achieve the same level of quality as H.264.1 There are some third-party apps such as UltraCorder which support H.265, but I’d prefer to stick with the stock camera app. I frequently use the handy “double tap power button” shortcut to quickly launch my camera app, so it is important that the app which launches is able to handle both photos and videos. This rules out using a specialty video app which supports H.265 encoding.
Converting a single video
It’s pretty easy to compress these videos using the
ffmpeg command line tool with something like the command below.
ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4
I tried a few different quality settings before settling on the default
-crf 28 . With this level, I cannot visually tell the difference in quality between compressed and uncompressed videos.
Converting videos in bulk
ffmpeg is great, but I wanted to batch process all of my phone videos, with the following goals in mind:
- Recursively search sub-directories, since I typically organize my photos and videos into a folder hierarchy.
- Only compress videos which are not already compressed (by using
ffprobeto detect if encoding is
- Preserve the metadata (creation time, modification time) from the original video, so that chronological sort continues to work properly.
So I wrote a small python CLI tool which achieves the above goals.
Put the script somewhere convenient (such as your home folder),
cd to your content directory, then call the script from the terminal using
python ~/compress_videos.py --recursive --file-ext=mp4 .
☠ Use at your own risk – I accept no responsibility for any data loss or mistakes caused by this script. It is a prudent idea to test it first and visually inspect the output. You should do so for each different input file you are converting. I ran into difficulty with a couple
.MTS video files which were interlaced, and so required different settings to convert properly.
CRF Guide (Constant Rate Factor in x264, x265 and libvpx) – A good overview of the difference between constant and variable bitrate encoding, and suggestions for sensible defaults for each.
A Large-Scale Comparison of x264, x265, and libvpx — a Sneak Peek (Netflix Tech Blog) ↩︎