Last active
May 24, 2023 09:13
-
-
Save Cygon/420c0fa894f96e2994c27d8b175576d4 to your computer and use it in GitHub Desktop.
Shell script that encodes a movie to the free AV1 video codec using the highest possible quality
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Helper script to transcode to high-quality AV1 clips via ffmpeg | |
# | |
# Uses best possible settings with two-pass encode. | |
# Encoding a full will take months or years! | |
# | |
# File from which the video is taken | |
inputFile=$1 | |
# File to which the final generated output video will be written | |
outputFile=${inputfile%.*}.av1transcoded.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:=72} | |
# 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} | |
# ----------------------------------------------------------------------------------------------- # | |
# Delete intermediate file if already there | |
if [[ -f ffmpeg2pass-0.log ]] | |
then | |
echo Deleting intermediate files... | |
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 | |
# ----------------------------------------------------------------------------------------------- # | |
# Video encoder settings | |
# | |
ffmpegParameters+=(-strict experimental) | |
ffmpegParameters+=(-c:v libaom-av1) | |
ffmpegParameters+=(-b:v $videoBitRate) | |
ffmpegParameters+=(-g $keyFrameInterval) | |
ffmpegParameters+=(-auto-alt-ref 1) | |
ffmpegParameters+=(-lag-in-frames 25) | |
ffmpegParameters+=(-crf 0) | |
#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 Encoding as 2x2 tiles | |
ffmpegParameters+=(-tile-columns 2) | |
ffmpegParameters+=(-tile-rows 2) | |
else | |
echo Encoding as single tile | |
fi | |
# ----------------------------------------------------------------------------------------------- # | |
# Audio encoder settings | |
# | |
ffmpegParameters+=(-c:a libopus) | |
ffmpegParameters+=(-b:a $audioBitRate) | |
ffmpegParameters+=(-ar 48000) | |
# ----------------------------------------------------------------------------------------------- # | |
# Other settings | |
# | |
ffmpegParameters+=(-threads 1) | |
# ----------------------------------------------------------------------------------------------- # | |
echo "ffmpeg options: ${ffmpegParameters[@]}" | |
# ----------------------------------------------------------------------------------------------- # | |
echo "==============================================================================" | |
echo "" | |
echo "Encoding first pass" | |
echo "" | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-shortest \ | |
"${ffmpegParameters[@]}" \ | |
-cpu-used 1 \ | |
-pass 1 \ | |
-f null \ | |
/dev/null | |
echo "==============================================================================" | |
echo "" | |
echo "Encoding second pass" | |
echo "" | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-shortest \ | |
"${ffmpegParameters[@]}" \ | |
-cpu-used 0 \ | |
-pass 2 \ | |
-y \ | |
$outputFile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment