Skip to main content

How to compress screen recordings

Install ffmpeg

brew install ffmpeg

Create the following file compress.sh

#!/usr/bin/env bash

# This script is used to compress screen recordings
# It aims at having an output file that is around 1 GB/hour
# and an encoding speed of around 1.5

# Usage
# ```
# compress.sh my_file.mp4
# ```
# You will get my_file-compressed.mp4 at the same location

# -i input
# -an no audio
# -r set framerate
# -c:v codec video
# -crf range is 0-51, 0 is lossless, 23 is default, 51 is worst quality (sane 15 to 23)
# -bf b-frames to look bak and forwar to increase the compression quality (sane 4 to 16)

file_input="${1}"
name_file_input_without_extension="${file_input%.*}"

list_params_x264=()
list_params_x264+=("--bitrate=2300") # bitrate for a target of 1 GB/hour
list_params_x264+=("--vbv-maxrate=4000") # VBV max bitrate
list_params_x264+=("--vbv-bufsize=8000") # VBV max bitrate
list_params_x264+=("--preset=fast")
list_params_x264+=("--crf=23")
list_params_x264+=("--ref=1") # Number of reference frames
list_params_x264+=("--bframes=4") # Number of consecutive B-frames (sane range 4 to 16)
list_params_x264+=("--no-interlaced")
list_params_x264+=("--frame-threads=auto") # Auto-detect suitable number of frame threads

# Set the IFS to `:` to join the array
ifs_old="${IFS}"
IFS=":"
string_params_x264="${list_params_x264[*]}"
IFS="${ifs_old}"

ffmpeg \
-i "${file_input}" \
-framerate 24 \
-r 24 \
-c:v libx264 \
-x264-params "${string_params_x264}" \
"${name_file_input_without_extension}-compressed.mp4"

Then make it executable

chmod +x compress.sh

Then you can run it on any videos like so

./compress.sh my_file.mp4

This is very useful for screen recordings.

It limits the framerate at 24 images per second and compresses using libx264.

You can also make it available in any directory by adding the script to path.