#!/bin/sh # TODO: Add hardware acceleration support # TODO: More consistently find a way to delete ffmpeg log files usage() { printf '%b\n' "${0##*/} -i [OPTIONS]" \ "\noptions:" \ "\t-c CODEC - video codec to use (default: libx264)" \ "\t-h - display this message" \ "\t-o FILE - output file (default: out.ext)" \ "\t-p PRESET - encoding preset to use" \ "\t-t FILE_SIZE - file size to target in MiB (default: 50)" } while [ "$*" ] do case $1 in - ) shift; continue ;; -- ) shift; break ;; -* ) flag=${1#-}; shift ;; * ) shift; continue ;; esac while [ "$flag" ] do arg=${flag%"${flag#?}"} case $arg in c ) VIDCOMP_CODEC=$1; shift ;; h ) usage; exit 0 ;; i ) VIDCOMP_INPUT_FILE=$1; shift ;; o ) VIDCOMP_OUTPUT_FILE=$1; shift ;; p ) VIDCOMP_PRESET=$1; shift ;; t ) VIDCOMP_TARGET_SIZE=$1; shift ;; * ) printf '%s\n' "${0##*/}: -$arg: invalid argument" 1>&2 usage 1>&2; exit 1 ;; esac flag=${flag#?} done done [ -z "$VIDCOMP_INPUT_FILE" ] && { printf '%s\n' "${0##*/}: missing input video" 1>&2 usage 1>&2; exit 1 } ext="${VIDCOMP_INPUT_FILE##.*}" : "${VIDCOMP_OUTPUT_FILE:=out.${ext}}" : "${VIDCOMP_CODEC:=libx264}" : "${VIDCOMP_TARGET_SIZE:=50}" a_bitrate="$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 \ "${VIDCOMP_INPUT_FILE}")" secs="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${VIDCOMP_INPUT_FILE}")" bitrate="$(fend floor \("${VIDCOMP_TARGET_SIZE} * 8388.608 / ${secs}" - \("${a_bitrate}" / 1000\)\))" ffmpeg -hide_banner -loglevel warning \ -i "${VIDCOMP_INPUT_FILE}" -c:v "${VIDCOMP_CODEC}" -b:v "${bitrate}k" \ ${VIDCOMP_PRESET:+"-preset" "$VIDCOMP_PRESET"} -pass 1 \ -an -f null -y /dev/null && \ ffmpeg -hide_banner -loglevel warning \ -i "${VIDCOMP_INPUT_FILE}" -c:v "${VIDCOMP_CODEC}" -b:v "${bitrate}k" \ ${VIDCOMP_PRESET:+"-preset" "$VIDCOMP_PRESET"} -pass 2 \ -c:a copy "${VIDCOMP_OUTPUT_FILE}"