diff options
| -rwxr-xr-x | transcode.sh | 731 |
1 files changed, 402 insertions, 329 deletions
diff --git a/transcode.sh b/transcode.sh index 1283ca3..33794bf 100755 --- a/transcode.sh +++ b/transcode.sh @@ -59,6 +59,24 @@ # Dennis Fink <me+coding@dennisfink.me> ############################################################################### +############################################################################### +# FILE STRUCTURE +# +# 1. Header, metadata, globals and exit codes +# 2. Function definitions +# - Output helpers +# - Help/version output +# - Small utility functions +# - Terminal color handling +# - Configuration handling +# - Codec skip-list handling +# - Preset handling +# - Cleanup handling +# - Size report handling +# - Encoding +# 3. Main execution +############################################################################### + # TRACE enables bash execution tracing and is intended for debugging control # flow / expansions. DEBUG enable structured debug messages (see debug()) and # is intended for high-level state reporting. @@ -107,6 +125,7 @@ set -o pipefail # for informational messages. They are marked readonly to prevent accidental # modification at runtime. ############################################################################### + readonly SCRIPTNAME=${0##*/} readonly DESCRIPTION="Batch transcode helper for media files using ffmpeg." readonly DATE_OF_CREATION=2025-08-06 @@ -189,12 +208,8 @@ EXIT_CONFIG_ERROR=3 EXIT_MISSING_DEPENDENCY=127 readonly EXIT_OK EXIT_RUNTIME_FAILURE EXIT_USAGE_ERROR EXIT_CONFIG_ERROR EXIT_MISSING_DEPENDENCY -############################################################################## -# FUNCTIONS -# -# This section defines the helper functions used throughout the script. They -# handle formatted output, error reporting, version information, utilities -# functions and runtime behaviour such as displaying usage instructions. +############################################################################### +# OUTPUT HELPERS ############################################################################### emit() { @@ -251,6 +266,10 @@ debug() { fi } +############################################################################### +# HELP AND VERSION OUTPUT +############################################################################### + print_help() { printf "${BOLD}${MAGENTA}%s${ALL_OFF} - ${BOLD}${CYAN}%s${ALL_OFF} - ${BOLD}%s${ALL_OFF} @@ -362,6 +381,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" \ "$DATE_OF_REVISION" "$LICENSE" } +############################################################################### +# SMALL UTILITY FUNCTIONS +############################################################################### + # Return the size of a file in bytes. # Uses GNU stat -c on Linux with a fallback to BSD/macOS stat -f. filesize() { @@ -381,35 +404,17 @@ format_filesize() { } ############################################################################### -# TERMINAL COLOR SETUP +# TERMINAL COLOR HANDLING # # Colors and style escape sequences are configured dynamically through the -# `setup_colors` function, which enables or disables color output based on the -# value of ENABLE_COLOR. When enabled, terminal capabilities are detected via -# `tput`, falling back to ANSI escapes if unavailable. +# setup_colors function. Runtime color detection happens in MAIN EXECUTION so +# all function definitions stay together before the executable flow. # # This script respects the NO_COLOR standard (https://no-color.org/). If the # environment variable NO_COLOR is set (to any value), all color output is # disabled. If FORCE_COLOR is set, colors are always enabled. ############################################################################### -# NOTE: This block calls debug() and reads $DEBUG. Both must be defined before -# this point. Do not move this block above the GLOBAL VARIABLES or FUNCTIONS -# sections without adjusting those dependencies. -if [[ -n "${NO_COLOR:-}" ]]; then - debug "Colors are disabled via NO_COLOR" - ENABLE_COLOR=0 -elif [[ -n "${FORCE_COLOR:-}" ]]; then - debug "Colors are forced via FORCE_COLOR" - ENABLE_COLOR=1 -elif [[ -t 1 ]]; then - debug "Colors are enabled via interactive terminal" - ENABLE_COLOR=1 -else - debug "Colors are disabled" - ENABLE_COLOR=0 -fi - setup_colors() { if [[ "$ENABLE_COLOR" -eq 1 ]]; then if tput setaf 0 >/dev/null 2>&1; then @@ -446,14 +451,9 @@ setup_colors() { CYAN="" fi } -setup_colors ############################################################################### -# MAIN EXECUTION -############################################################################### - -############################################################################### -# CONFIGURATION FILE +# CONFIGURATION HANDLING # # Load defaults from config.toml if it exists. Values are only applied when the # corresponding CLI flag has NOT already been set (CLI takes precedence). @@ -635,11 +635,14 @@ load_config() { fi } +############################################################################### +# CODEC SKIP-LIST HANDLING +############################################################################### + # Add a codec name to the SKIP_CODECS associative array. # - Normalizes to lowercase # - Ignores empty tokens # - Used both for CLI --skip-codec and for codecs defined -# in the config file add_skip_codec_token() { local token="${1,,}" # lowercase if [[ ! -v SKIP_CODECS["$token"] ]]; then @@ -662,6 +665,10 @@ parse_skip_codec_parameter() { done } +############################################################################### +# PRESET HANDLING +############################################################################### + # Load ffmpeg argument preset by name. # # Security: @@ -792,300 +799,9 @@ list_presets() { done } -if [[ $# -eq 0 ]]; then - debug "No parameters were specified" - printf "${BOLD}${BLUE}Usage:${ALL_OFF} ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}[OPTION] [--]${ALL_OFF} ${BOLD}${GREEN}FILE...${ALL_OFF} -Run ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}--help${ALL_OFF} for full usage information.\n" "$SCRIPTNAME" "$SCRIPTNAME" >&2 - exit $EXIT_USAGE_ERROR -fi - -while [[ $# -gt 0 ]]; do - case "$1" in - -h | --help | -\?) - print_help - exit $EXIT_OK - ;; - --version) - print_version - exit $EXIT_OK - ;; - --list-presets) - list_presets - exit $EXIT_OK - ;; - -q | --quiet) - QUIET=1 - _CLI_QUIET=1 - shift - ;; - -v | --verbose) - VERBOSE=1 - _CLI_VERBOSE=1 - shift - ;; - --color) - ENABLE_COLOR=1 - setup_colors - shift - ;; - --no-color) - ENABLE_COLOR=0 - setup_colors - shift - ;; - -c | --continue) - CONTINUE_ON_FAIL=1 - _CLI_CONTINUE=1 - shift - ;; - --no-continue) - CONTINUE_ON_FAIL=0 - _CLI_CONTINUE=1 - shift - ;; - --verify-output) - VERIFY_OUTPUT=1 - _CLI_VERIFY_OUTPUT=1 - shift - ;; - --no-verify-output) - VERIFY_OUTPUT=0 - _CLI_VERIFY_OUTPUT=1 - shift - ;; - --config-file) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - if [[ ! -n "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - CONFIG_FILE="$2" - _CLI_CONFIG_FILE=1 - shift 2 - ;; - --config-file=*) - if [[ ! -n "${1#*=}" ]]; then - error "Value for --config-file must not be empty" - exit $EXIT_USAGE_ERROR - fi - CONFIG_FILE="${1#*=}" - _CLI_CONFIG_FILE=1 - shift - ;; - --no-config) - CONFIG_FILE="/dev/null" - _CLI_CONFIG_FILE=1 - shift - ;; - -f | --encode-file) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - if [[ ! -n "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - ENCODE_FILE="$2" - shift 2 - ;; - --encode-file=*) - if [[ ! -n "${1#*=}" ]]; then - error "Value for --encode-file must not be empty" - exit $EXIT_USAGE_ERROR - fi - ENCODE_FILE="${1#*=}" - shift - ;; - -n | --dry-run) - DRY_RUN=1 - shift - ;; - -N | --nice) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - NICE_VALUE="$2" - _CLI_NICE=1 - shift 2 - ;; - --nice=*) - NICE_VALUE="${1#*=}" - _CLI_NICE=1 - shift - ;; - -s | --size-report) - SIZE_REPORT=1 - _CLI_SIZE_REPORT=1 - shift - ;; - --no-size-report) - SIZE_REPORT=0 - _CLI_SIZE_REPORT=1 - shift - ;; - --size-report-file) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - if [[ ! -n "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - SIZE_REPORT_FILE="$2" - _CLI_SIZE_REPORT_FILE=1 - shift 2 - ;; - --size-report-file=*) - if [[ ! -n "${1#*=}" ]]; then - error "Value for --size-report-file must not be empty" - exit $EXIT_USAGE_ERROR - fi - SIZE_REPORT_FILE="${1#*=}" - _CLI_SIZE_REPORT_FILE=1 - shift - ;; - -S | --skip-codec) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - parse_skip_codec_parameter "$2" - shift 2 - ;; - --skip-codec=*) - parse_skip_codec_parameter "${1#*=}" - shift - ;; - -l | --only-if-smaller) - ONLY_IF_SMALLER=1 - _CLI_ONLY_IF_SMALLER=1 - shift - ;; - --no-only-if-smaller) - ONLY_IF_SMALLER=0 - _CLI_ONLY_IF_SMALLER=1 - shift - ;; - --hwaccel) - HWACCEL=1 - # Peek at the next argument: use it as the METHOD only if it is - # non-empty and does not look like an option flag. - if [[ $# -ge 2 && -n "$2" && "$2" != -* ]]; then - HWACCEL_VALUE="$2" - shift 2 - else - HWACCEL_VALUE="auto" - shift - fi - _CLI_HWACCEL=1 - ;; - --hwaccel=*) - HWACCEL=1 - HWACCEL_VALUE="${1#*=}" - if [[ ! -n "$HWACCEL_VALUE" ]]; then - error "Value for --hwaccel must not be empty" - exit $EXIT_USAGE_ERROR - fi - _CLI_HWACCEL=1 - shift - ;; - --no-hwaccel) - HWACCEL=0 - _CLI_HWACCEL=1 - shift - ;; - -p | --preset) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - if [[ ! -n "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - PRESET_NAME="$2" - _CLI_PRESET=1 - shift 2 - ;; - --preset=*) - if [[ ! -n "${1#*=}" ]]; then - error "Value for --preset must not be empty" - exit $EXIT_USAGE_ERROR - fi - PRESET_NAME="${1#*=}" - _CLI_PRESET=1 - shift - ;; - --) - shift - REMAINING_ARGS+=("$@") - break - ;; - -*) - error "Unknown option: $1" - exit $EXIT_USAGE_ERROR - ;; - *) - REMAINING_ARGS+=("$1") - shift - ;; - esac -done - -# Apply config file defaults. Must run after CLI parsing so _CLI_* sentinels -# are set, but before validation so config-supplied values are validated too. -load_config - -printf -v joined ' %s' "${!SKIP_CODECS[@]}" - -debug "Effective configuration:" -debug " config-file:" "$CONFIG_FILE" -debug " dry-run:" "$DRY_RUN" -debug " encode-file:" "$ENCODE_FILE" -debug " hwaccel:" "$HWACCEL" -debug " hwaccel_value:" "$HWACCEL_VALUE" -debug " nice:" "$NICE_VALUE" -debug " only-if-smaller:" "$ONLY_IF_SMALLER" -debug " preset:" "$PRESET_NAME" -debug " quiet:" "$QUIET" -debug " size-report-file:" "$SIZE_REPORT_FILE" -debug " size-report:" "$SIZE_REPORT" -debug " skip-codecs:" "${joined# }" -debug " verbose:" "$VERBOSE" -debug " verify-output:" "$VERIFY_OUTPUT" - -command -v ffmpeg >/dev/null 2>&1 || { - error "ffmpeg not found." - exit $EXIT_MISSING_DEPENDENCY -} -command -v ffprobe >/dev/null 2>&1 || { - error "ffprobe not found." - exit $EXIT_MISSING_DEPENDENCY -} -command -v nice >/dev/null 2>&1 || { - error "nice not found." - exit $EXIT_MISSING_DEPENDENCY -} - -if [[ $_CLI_SIZE_REPORT_FILE -eq 1 && $SIZE_REPORT -eq 0 ]]; then - warn "--size-report-file has no effect without --size-report" -fi - -if [[ ! "$NICE_VALUE" =~ ^-?[0-9]+$ || $NICE_VALUE -lt -20 || $NICE_VALUE -gt 19 ]]; then - error "Invalid nice value (must be an integer between -20 and 19):" "$NICE_VALUE" - exit $EXIT_USAGE_ERROR -fi - -if [[ ! -z "${joined# }" ]]; then - verbose "Skipping files with codecs:" "${joined# }" -fi -unset joined +############################################################################### +# CLEANUP HANDLING +############################################################################### # Remove temporary output files created during encoding. # Registered via trap EXIT so it runs on normal exit and on failures @@ -1100,7 +816,10 @@ cleanup() { fi done } -trap cleanup EXIT + +############################################################################### +# SIZE REPORT HANDLING +############################################################################### # Calculate integer percentage saved from original/new byte counts. calculate_saved_percentage() { @@ -1187,6 +906,10 @@ print_size_report_summary() { printf "${BOLD}${BLUE}Average saved:${ALL_OFF} %s%%\n" "$average_saved_pct" } +############################################################################### +# ENCODING +############################################################################### + # Encode a single media file according to PRESET_NAME. # # Arguments: @@ -1210,6 +933,10 @@ encode_one() { local current_file_index="$2" local amount_total_files="$3" + # --------------------------------------------------------------------------- + # Validate input file + # --------------------------------------------------------------------------- + # Ignore empty input entries so callers can safely pass filtered file lists # without treating blank lines as errors. if [[ -z "$input_file" ]]; then @@ -1242,6 +969,10 @@ encode_one() { return $EXIT_RUNTIME_FAILURE fi + # --------------------------------------------------------------------------- + # Probe input stream metadata + # --------------------------------------------------------------------------- + # Probe codec, pixel format and frame rate in a single ffprobe invocation to # decrease the startup overhead on large batches. local probe_out @@ -1286,6 +1017,10 @@ encode_one() { return $EXIT_RUNTIME_FAILURE fi + # --------------------------------------------------------------------------- + # Derive output pixel format and GOP size + # --------------------------------------------------------------------------- + # Some files report "yuvj*" formats (full-range JPEG-style). For encoding # purposes we normalize to the equivalent "yuv*" formats. input_pixel_format="${input_pixel_format/yuvj/yuv}" @@ -1342,6 +1077,10 @@ encode_one() { load_preset "$PRESET_NAME" + # --------------------------------------------------------------------------- + # Build temporary output path and ffmpeg command + # --------------------------------------------------------------------------- + local extension directory temporary_output_file base stem base="${input_file##*/}" @@ -1389,6 +1128,10 @@ encode_one() { "${ffargs[@]}" "file:$temporary_output_file") + # --------------------------------------------------------------------------- + # Dry-run output + # --------------------------------------------------------------------------- + if [[ $DRY_RUN -eq 1 ]]; then msg "DRY RUN:" "Would encode with preset $PRESET_NAME" verbose "Input codec:" "$input_codec" @@ -1401,6 +1144,10 @@ encode_one() { return $EXIT_OK fi + # --------------------------------------------------------------------------- + # Run encode, verify output, and replace original + # --------------------------------------------------------------------------- + msg "Encoding:" "$input_file" if nice -n "$NICE_VALUE" "${encode_cmd[@]}"; then @@ -1467,6 +1214,332 @@ encode_one() { fi } +############################################################################### +# MAIN EXECUTION +############################################################################### + +# Configure terminal colors before any user-facing output. +# +# NOTE: This block calls debug() and reads $DEBUG. Both must be defined before +# this point. Do not move this block above the GLOBAL VARIABLES or FUNCTION +# DEFINITIONS sections without adjusting those dependencies. +if [[ -n "${NO_COLOR:-}" ]]; then + debug "Colors are disabled via NO_COLOR" + ENABLE_COLOR=0 +elif [[ -n "${FORCE_COLOR:-}" ]]; then + debug "Colors are forced via FORCE_COLOR" + ENABLE_COLOR=1 +elif [[ -t 1 ]]; then + debug "Colors are enabled via interactive terminal" + ENABLE_COLOR=1 +else + debug "Colors are disabled" + ENABLE_COLOR=0 +fi +setup_colors + +# Reject calls without any positional arguments or options before doing more +# setup work. +if [[ $# -eq 0 ]]; then + debug "No parameters were specified" + printf "${BOLD}${BLUE}Usage:${ALL_OFF} ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}[OPTION] [--]${ALL_OFF} ${BOLD}${GREEN}FILE...${ALL_OFF} +Run ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}--help${ALL_OFF} for full usage information.\n" "$SCRIPTNAME" "$SCRIPTNAME" >&2 + exit $EXIT_USAGE_ERROR +fi + +# Parse command-line options. CLI flags are recorded in _CLI_* sentinel +# variables so load_config() can respect CLI-over-config precedence. +while [[ $# -gt 0 ]]; do + case "$1" in + -h | --help | -\?) + print_help + exit $EXIT_OK + ;; + --version) + print_version + exit $EXIT_OK + ;; + --list-presets) + list_presets + exit $EXIT_OK + ;; + -q | --quiet) + QUIET=1 + _CLI_QUIET=1 + shift + ;; + -v | --verbose) + VERBOSE=1 + _CLI_VERBOSE=1 + shift + ;; + --color) + ENABLE_COLOR=1 + setup_colors + shift + ;; + --no-color) + ENABLE_COLOR=0 + setup_colors + shift + ;; + -c | --continue) + CONTINUE_ON_FAIL=1 + _CLI_CONTINUE=1 + shift + ;; + --no-continue) + CONTINUE_ON_FAIL=0 + _CLI_CONTINUE=1 + shift + ;; + --verify-output) + VERIFY_OUTPUT=1 + _CLI_VERIFY_OUTPUT=1 + shift + ;; + --no-verify-output) + VERIFY_OUTPUT=0 + _CLI_VERIFY_OUTPUT=1 + shift + ;; + --config-file) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ ! -n "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + CONFIG_FILE="$2" + _CLI_CONFIG_FILE=1 + shift 2 + ;; + --config-file=*) + if [[ ! -n "${1#*=}" ]]; then + error "Value for --config-file must not be empty" + exit $EXIT_USAGE_ERROR + fi + CONFIG_FILE="${1#*=}" + _CLI_CONFIG_FILE=1 + shift + ;; + --no-config) + CONFIG_FILE="/dev/null" + _CLI_CONFIG_FILE=1 + shift + ;; + -f | --encode-file) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ ! -n "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + ENCODE_FILE="$2" + shift 2 + ;; + --encode-file=*) + if [[ ! -n "${1#*=}" ]]; then + error "Value for --encode-file must not be empty" + exit $EXIT_USAGE_ERROR + fi + ENCODE_FILE="${1#*=}" + shift + ;; + -n | --dry-run) + DRY_RUN=1 + shift + ;; + -N | --nice) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + NICE_VALUE="$2" + _CLI_NICE=1 + shift 2 + ;; + --nice=*) + NICE_VALUE="${1#*=}" + _CLI_NICE=1 + shift + ;; + -s | --size-report) + SIZE_REPORT=1 + _CLI_SIZE_REPORT=1 + shift + ;; + --no-size-report) + SIZE_REPORT=0 + _CLI_SIZE_REPORT=1 + shift + ;; + --size-report-file) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ ! -n "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + SIZE_REPORT_FILE="$2" + _CLI_SIZE_REPORT_FILE=1 + shift 2 + ;; + --size-report-file=*) + if [[ ! -n "${1#*=}" ]]; then + error "Value for --size-report-file must not be empty" + exit $EXIT_USAGE_ERROR + fi + SIZE_REPORT_FILE="${1#*=}" + _CLI_SIZE_REPORT_FILE=1 + shift + ;; + -S | --skip-codec) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + parse_skip_codec_parameter "$2" + shift 2 + ;; + --skip-codec=*) + parse_skip_codec_parameter "${1#*=}" + shift + ;; + -l | --only-if-smaller) + ONLY_IF_SMALLER=1 + _CLI_ONLY_IF_SMALLER=1 + shift + ;; + --no-only-if-smaller) + ONLY_IF_SMALLER=0 + _CLI_ONLY_IF_SMALLER=1 + shift + ;; + --hwaccel) + HWACCEL=1 + # Peek at the next argument: use it as the METHOD only if it is + # non-empty and does not look like an option flag. + if [[ $# -ge 2 && -n "$2" && "$2" != -* ]]; then + HWACCEL_VALUE="$2" + shift 2 + else + HWACCEL_VALUE="auto" + shift + fi + _CLI_HWACCEL=1 + ;; + --hwaccel=*) + HWACCEL=1 + HWACCEL_VALUE="${1#*=}" + if [[ ! -n "$HWACCEL_VALUE" ]]; then + error "Value for --hwaccel must not be empty" + exit $EXIT_USAGE_ERROR + fi + _CLI_HWACCEL=1 + shift + ;; + --no-hwaccel) + HWACCEL=0 + _CLI_HWACCEL=1 + shift + ;; + -p | --preset) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ ! -n "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + PRESET_NAME="$2" + _CLI_PRESET=1 + shift 2 + ;; + --preset=*) + if [[ ! -n "${1#*=}" ]]; then + error "Value for --preset must not be empty" + exit $EXIT_USAGE_ERROR + fi + PRESET_NAME="${1#*=}" + _CLI_PRESET=1 + shift + ;; + --) + shift + REMAINING_ARGS+=("$@") + break + ;; + -*) + error "Unknown option: $1" + exit $EXIT_USAGE_ERROR + ;; + *) + REMAINING_ARGS+=("$1") + shift + ;; + esac +done + +# Apply config file defaults. Must run after CLI parsing so _CLI_* sentinels +# are set, but before validation so config-supplied values are validated too. +load_config + +printf -v joined ' %s' "${!SKIP_CODECS[@]}" + +debug "Effective configuration:" +debug " config-file:" "$CONFIG_FILE" +debug " dry-run:" "$DRY_RUN" +debug " encode-file:" "$ENCODE_FILE" +debug " hwaccel:" "$HWACCEL" +debug " hwaccel_value:" "$HWACCEL_VALUE" +debug " nice:" "$NICE_VALUE" +debug " only-if-smaller:" "$ONLY_IF_SMALLER" +debug " preset:" "$PRESET_NAME" +debug " quiet:" "$QUIET" +debug " size-report-file:" "$SIZE_REPORT_FILE" +debug " size-report:" "$SIZE_REPORT" +debug " skip-codecs:" "${joined# }" +debug " verbose:" "$VERBOSE" +debug " verify-output:" "$VERIFY_OUTPUT" + +command -v ffmpeg >/dev/null 2>&1 || { + error "ffmpeg not found." + exit $EXIT_MISSING_DEPENDENCY +} +command -v ffprobe >/dev/null 2>&1 || { + error "ffprobe not found." + exit $EXIT_MISSING_DEPENDENCY +} +command -v nice >/dev/null 2>&1 || { + error "nice not found." + exit $EXIT_MISSING_DEPENDENCY +} + +if [[ $_CLI_SIZE_REPORT_FILE -eq 1 && $SIZE_REPORT -eq 0 ]]; then + warn "--size-report-file has no effect without --size-report" +fi + +if [[ ! "$NICE_VALUE" =~ ^-?[0-9]+$ || $NICE_VALUE -lt -20 || $NICE_VALUE -gt 19 ]]; then + error "Invalid nice value (must be an integer between -20 and 19):" "$NICE_VALUE" + exit $EXIT_USAGE_ERROR +fi + +if [[ ! -z "${joined# }" ]]; then + verbose "Skipping files with codecs:" "${joined# }" +fi +unset joined + +# Remove temporary output files on normal exit and on failures. +trap cleanup EXIT + STATUS=$EXIT_OK if [[ -n $ENCODE_FILE ]]; then if [[ ! -f "$ENCODE_FILE" ]]; then |
