#!/bin/sh error() { echo "$@" >&2 exit 1 } set_video() { local hw preset='-preset slow' case "$1" in copy) codec=copy hw=0 ;; h264_sw) codec=libx264 hw=0 ;; h264_hw) codec=h264_qsv hw=1 ;; h265_sw) codec=libx265 tag='-tag:v hvc1' # this is needed by broken devices like Apple ones hw=0 ;; h265_hw) codec=hevc_qsv tag='-tag:v hvc1' hw=1 ;; av1_sw) codec=libsvtav1 preset='-preset 6' hw=0 ;; av1_hw) codec=av1_qsv hw=1 ;; *) error "Invalid video codec '$1'" ;; esac if [ $hw -eq 1 ]; then hwaccel='-hwaccel qsv -hwaccel_output_format qsv' # see https://github.com/intel/media-delivery/blob/master/doc/quality.rst quality=" -global_quality $q -g 256 -bf 7 -extbrc 1 -look_ahead_depth 40 -b_strategy 1 -refs 5 -adaptive_i 1 -adaptive_b 1 -strict -1 " else quality="-crf $q" fi } codec=av1_hw q=25 getopts=':v:q:h' usage() { cat <<- EOF Usage: ${0##*/} [-v codec] [-q quality] video codecs: copy, h264_sw, h264_hw, h265_sw, h265_hw, av1_sw, av1_hw. Default av1_hw quality: 1-51 (lower is better). Default 25 EOF exit $1 } while getopts $getopts arg; do case "$arg" in v) codec=$OPTARG ;; h) usage 0 ;; q) q=$OPTARG case "$q" in *[!0-9]*) usage 1 ;; esac { [ "$q" -lt 1 ] || [ "$q" -gt 51 ] ; } && usage 1 ;; *) usage 1 ;; esac done shift $((OPTIND - 1)) in=$1 out=$2 [ $# -ne 2 ] && usage 1 [ -f "$in" ] || error "file '$in' not found" set_video "$codec" exec ffmpeg -y -loglevel quiet -stats $hwaccel -i "$in" -c:v $codec $preset $quality $tag -c:a copy "$out"