Skip to content

Instantly share code, notes, and snippets.

@Cygon
Last active May 5, 2023 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cygon/c19e0bff6d5fe3d2eea1f0535e491ebf to your computer and use it in GitHub Desktop.
Save Cygon/c19e0bff6d5fe3d2eea1f0535e491ebf to your computer and use it in GitHub Desktop.
Shell script that encodes a VP9 `.webm` movie with the highest possible quality
#!/bin/sh
# Helper script to transcode movies using the free VP9 codec
# in very high quality (a full movie will take several days!)
#
# File from which the video is taken
inputFile=$1
# File to which the final generated output video will be written
outputFile=${inputfile%.*}.vp9transcoded.webm
# Whether to encode the video into 2x2 tiles instead of whole
#
# Allows decoders to decode single frames with up to 4 threads
# Might not be necessary for modern decoders (which simply decode
# 4 frames in parallel, thereby achieving the same without tiles.
# Also lowers quality/efficiency a little bit.
#
: ${useFourTiles:=false}
# Bits per second to use for the video and audio streams
#
# Suggested for stereo movies | Suggested for 5.1 movies
# --------------------------------|--------------------------------
# 768 = 672 video + 96 audio
# 1024 = 928 video + 96 audio
# 1536 = 1408 video + 128 audio 1536 = 1280 video + 256 audio
# 2048 = 1920 video + 128 audio 2048 = 1792 video + 256 audio
# 2560 = 2432 video + 128 audio 2560 = 2152 video + 384 audio
# 3072 = 2944 video + 128 audio 3072 = 2688 video + 384 audio
# 4096 = 3968 video + 128 audio 4096 = 3712 video + 384 audio
# 5120 = 4992 video + 128 audio 5120 = 4736 video + 384 audio
# 6144 = 5670 video + 384 audio
: ${videoBitRate:=2432}
: ${audioBitRate:=128}
# After how many frames to force a keyframe
#
# More keyframes worsen overall compression but allow better seeking.
# Many encoders recommend one keyframe per second, but one every two
# seconds is much more sensible imho.
#
: ${keyFrameInterval:=60}
# Whether to do a 10-bit encode
#
# Ten bit encodes are claimed to avoid banding, but I've yet to see
# any of it in a high-quality 8-bit encode.
#
: ${tenBit:=false}
# Set to crop the video
#
# Should be set to "width:height:offsetX:offsetY" if used
# Leave set to false in order to perform no cropping at all
#
: ${cropBoundaries:=false}
# Whether to sharpen the video
#
: ${sharpenVideo:=false}
# ----------------------------------------------------------------------------------------------- #
echo ==========================================================================
# Delete intermediate file if already there
if [[ -f ffmpeg2pass-0.log ]]
then
rm ffmpeg2pass-0.log
fi
ffmpegParameters=()
# If the user has specified cropping bounds, set up the respective ffmpeg parameter
if [ "$cropBoundaries" = false ]
then
echo Cropping disabled.
else
echo Cropping to $cropBoundaries
ffmpegParameters+=(-filter:v crop=$cropBoundaries)
fi
# If the user has specified cropping bounds, set up the respective ffmpeg parameter
if [ "$sharpenVideo" = false ]
then
echo Sharpening disabled.
else
echo Sharpening via smartblur filter.
ffmpegParameters+=(-filter:v smartblur=1.5:-0.35:-3.5:0.65:0.25:2.0)
fi
#ffmpegParameters+=(-filter_complex "drawbox=enable='between(n,0,180)':x=180:y=96:w=288:h=56:color=black:t=fill")
# ----------------------------------------------------------------------------------------------- #
# Video encoder settings
#
ffmpegParameters+=(-c:v libvpx-vp9)
ffmpegParameters+=(-b:v $videoBitRate)
ffmpegParameters+=(-g $keyFrameInterval)
ffmpegParameters+=(-auto-alt-ref 1)
ffmpegParameters+=(-lag-in-frames 25)
ffmpegParameters+=(-crf 0)
ffmpegParameters+=(-quality best)
ffmpegParameters+=(-deadline best)
ffmpegParameters+=(-threads 1)
#ffmpegParameters+=(-frame-parallel 1)
if [ "$tenBit" = true ]
then
echo 10-bit encode
ffmpegParameters+=(-pix_fmt yuv420p10le)
else
echo 8-bit encode
ffmpegParameters+=(-pix_fmt yuv420p)
fi
if [ "$useFourTiles" = true ]
then
echo 2x2 Tiles
ffmpegParameters+=(-tile-columns 2)
ffmpegParameters+=(-tile-rows 2)
else
echo Single Tile
fi
# ----------------------------------------------------------------------------------------------- #
# Audio encoder settings
#
ffmpegParameters+=(-c:a libopus)
ffmpegParameters+=(-b:a $audioBitRate)
ffmpegParameters+=(-ar 48000)
# ----------------------------------------------------------------------------------------------- #
echo "ffmpeg options: ${ffmpegParameters[@]}"
# First pass
ffmpeg \
-hide_banner \
-i "$inputFile" \
-shortest \
"${ffmpegParameters[@]}" \
-cpu-used 1 \
-speed 1 \
-pass 1 \
-f null \
/dev/null
# Second pass
ffmpeg \
-hide_banner \
-i "$inputFile" \
-shortest \
"${ffmpegParameters[@]}" \
-cpu-used 0 \
-speed 0 \
-pass 2 \
-y \
transcoded-vp9.webm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment