Skip to content

Instantly share code, notes, and snippets.

@Konfekt
Last active March 13, 2021 09:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Konfekt/7cb81c73a8c8e47dc0f80d1347fe7db0 to your computer and use it in GitHub Desktop.
Save Konfekt/7cb81c73a8c8e47dc0f80d1347fe7db0 to your computer and use it in GitHub Desktop.
convert video files into the WebM format in batches using ffmpeg (and preferrably GNU parallel)
#!/bin/sh
# convert video files into the WebM format in batches using ffmpeg (and preferrably GNU parallel)
# exit on error or use of undeclared variable or pipe error:
set -o errexit -o nounset -o pipefail
# -crf 10 : Constant Rate Factor (crf) gives video quality from 0 (lossless) to 63 (worst); default is 23.
# -c:a/v ... = transform the audio/video data using ...
# -b:a/v ... = audio/video bitrate is ...
# -cpu-used : from 0 (default) to 5. Use 1 or 2 for faster but worse encoding
# -row-mt 1 = better multi-threading supported since libvpx 1.6
# see https://trac.ffmpeg.org/wiki/Encode/VP9
# https://github.com/Kagami/webm.py/wiki/Notes-on-encoding-settings
# https://blog.programster.org/VP9-encoding
# https://developers.google.com/media/vp9/settings/vod/
# and https://notepad.patheticcockroach.com/4263/a-brief-tutorial-to-encode-in-x265-and-opus-using-ffmpeg/
convert() {
cpu_cores="$(getconf _NPROCESSORS_ONL)"
# Single pass for faster conversion:
# ffmpeg \
# -y -loglevel error \
# -i "$1" \
# -threads "${cpu_cores:-1}" -cpu-used 1 -quality good \
# -tile-columns 2 -frame-parallel 0 -auto-alt-ref 1 -lag-in-frames 25 \
# -c:v libvpx-vp9 -b:v 750k -minrate 375k -maxrate 1088k -crf 33 \
# -c:a libopus -ac 2 -b:a 48k -vbr on -compression_level 10 -frame_duration 40 -application audio \
# -movflags faststart \
# "${1%.[^.]*}".webm
# Double pass for better quality:
echo "Started first pass processing $1 ..."
ffmpeg \
-y -loglevel error \
-i "$1" \
-pass 1 -speed 4 \
-threads "${cpu_cores:-1}" -cpu-used 1 -quality good \
-tile-columns 4 -frame-parallel 0 -auto-alt-ref 1 -lag-in-frames 25 \
-c:v libvpx-vp9 -b:v 750k -minrate 375k -maxrate 1088k -crf 33 \
-c:a libopus -ac 2 -b:a 48k -vbr on -compression_level 10 -frame_duration 40 -application audio \
-movflags faststart \
-f webm \
/dev/null &&
echo "... finished first and started second pass processing $1 ..."
ffmpeg \
-y -loglevel error \
-i "$1" \
-pass 2 -speed 1 \
-threads "${cpu_cores:-1}" -cpu-used 1 -quality good \
-tile-columns 4 -frame-parallel 0 -auto-alt-ref 1 -lag-in-frames 25 \
-c:v libvpx-vp9 -b:v 750k -minrate 375k -maxrate 1088k -crf 33 \
-c:a libopus -ac 2 -b:a 48k -vbr on -compression_level 10 -frame_duration 40 -application audio \
-movflags faststart \
"${1%.[^.]*}".webm &&
echo "... finished second and last pass processing $1."
} && export -f convert
if command -v parallel >/dev/null 2>&1; then
parallel convert {} ::: "$@"
else
for f in "$@"; do
convert "$f"
done
fi
@Konfekt
Copy link
Author

Konfekt commented May 8, 2020

This blog entry discusses the choices made in this script.

@kwbr
Copy link

kwbr commented May 20, 2020

Nice script. I try to adapt it for my own needs.
The first pass is missing a "-f webm"

@Konfekt
Copy link
Author

Konfekt commented May 22, 2020

Thank you! Fixed here and in the blog post.

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