#!/bin/sh set -u MAX_MIN_DIM=720 if test $# -lt 2 || test $# -gt 3; then printf 'usage: %s input-file output-file [max-min-dim]' "$0" >&2 exit 3 fi err () { colour="$1" format="$2" shift 2 printf '\x1b['"${colour}m${format}"'\x1b[m\n' "$@" >&2 } alert () { err "1;31" "$@"; } header () { err "1;34" "$@"; } subheader () { err "34" "$@"; } red () { err "31" "$@"; } green () { err "32" "$@"; } yellow () { err "33" "$@"; } magenta () { err "35" "$@"; } cyan () { err "36" "$@"; } input="$1" output="$2" if test $# -ge 3; then MAX_MIN_DIM="$3" fi if test ! -f "$input" || test ! -r "$input"; then red 'Input file %s does not exist or is not a readable file, skipping' exit 2 fi if test -e "$output" || test -L "$output"; then red 'Output file %s already exists, skipping' exit 2 fi header 'Transcoding %s' "$input" subheader 'Outputing to %s' "$output" dimensions=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 -- "$input") if test -z "$dimensions"; then red 'An error occured, skipping' exit 2 fi oldwidth=$(printf '%s\n' "$dimensions" | cut -d 'x' -f 1) oldheight=$(printf '%s\n' "$dimensions" | cut -d 'x' -f 2) if test -z "$oldwidth" || test -z "$oldheight"; then red 'An error occured, skipping' exit 2 fi scale= if test "$oldwidth" -lt "$oldheight"; then if test "$oldwidth" -gt "${MAX_MIN_DIM}"; then magenta 'The smaller dimension (width) was %i, downscaling to %i' "$oldwidth" "${MAX_MIN_DIM}" newwidth="${MAX_MIN_DIM}" newheight=-2 scale="-vf scale=$newwidth:$newheight" else cyan 'The smaller dimension (width) was %i, keeping as it does not exceed %i' "$oldwidth" "${MAX_MIN_DIM}" fi else if test "$oldheight" -gt "${MAX_MIN_DIM}"; then magenta 'The smaller dimension (height) was %i, downscaling to %i' "$oldheight" "${MAX_MIN_DIM}" newwidth=-2 newheight="${MAX_MIN_DIM}" scale="-vf scale=$newwidth:$newheight" else cyan 'The smaller dimension (height) was %i, keeping as it does not exceed %i' "$oldheight" "${MAX_MIN_DIM}" fi fi if test -z "$scale"; then codec="$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 -- "$input")" if test -z "$codec"; then red 'An error occured, skipping' exit 2 fi if test "$codec" = hevc; then cyan 'Already encoded with HEVC, keeping video codec' codec="-c:v copy" else magenta 'Encoded with %s, transcoding to HEVC' "$codec" codec="-c:v libx265" fi else codec="-c:v libx265" fi if test -z "$scale" && test "$codec" = '-c:v copy'; then yellow 'The video is already small and encoded in HEVC, skipping' exit 1 fi ffmpeg -i "$input" $scale $codec -c:a copy -- "$output" ret=$? if test $ret = 0; then oldsize=$(stat -c '%s' -- "$input") newsize=$(stat -c '%s' -- "$output") if test $newsize -ge $oldsize; then p=$(( 100 * (newsize - oldsize) / oldsize )) yellow 'The transcoded video was larger than the original (would increase by %i%%), skipping' $p if ! rm -- "$output"; then alert 'Failed to remove old file: %s' "$output" fi exit 1 else p=$(( 100 * (oldsize - newsize) / oldsize )) green 'The transcoded video was smaller than the original (reduced by %i%%), keeping' $p exit 0 fi else red 'An error occured, skipping' if ! rm -- "$output"; then alert 'Failed to remove old file: %s' "$output" fi exit 2 fi