Skip to content

Instantly share code, notes, and snippets.

@lord-carlos
Last active September 21, 2022 19:29
Show Gist options
  • Save lord-carlos/c9984339b722f478793d18bf2dda14b2 to your computer and use it in GitHub Desktop.
Save lord-carlos/c9984339b722f478793d18bf2dda14b2 to your computer and use it in GitHub Desktop.
Window WSL bash script to encode videos to under 8mb for discord sharing. Needs ffmpeg.exe in path
#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset
#set -x #Debug
#
# Re-encode a video to a target size in MB.
# Example:
# ./8mb2.bash video.mp4 8
# Currently only supports files from current dir. Script can be where ever.
############
# Credit to Marian Minar
# https://stackoverflow.com/a/61146975/2001062
# Re written by lord-carlos
# Inspired by djkato https://github.com/djkato/Discord-Media-Compressor-sub-8mb
T_SIZE="$2" # target size in MB
T_FILE="${1%.*}-$2MB.webm" # filename out
target=$(wslpath -w "$1")
null=$(wslpath -w "/dev/null")
main () {
# Original duration in seconds
O_DUR=$(\
ffprobe.exe \
-v error \
-show_entries format=duration \
-of csv=p=0 "${target}")
# Original audio rate
O_ARATE=$(\
ffprobe.exe \
-v error \
-select_streams a:0 \
-show_entries stream=bit_rate \
-of csv=p=0 "${target}")
# Original audio rate in KiB/s
O_ARATE=$(\
awk \
-v arate="$O_ARATE" \
'BEGIN { printf "%.0f", (arate / 1024) }')
# Target size is required to be less than the size of the original audio stream
T_MINSIZE=$(\
awk \
-v arate="$O_ARATE" \
-v duration="$O_DUR" \
'BEGIN { printf "%.2f", ( (arate * duration) / 8192 ) }')
# Equals 1 if target size is ok, 0 otherwise
IS_MINSIZE=$(\
awk \
-v size="$T_SIZE" \
-v minsize="$T_MINSIZE" \
'BEGIN { print (minsize < size) }')
# Give useful information if size is too small
if [[ $IS_MINSIZE -eq 0 ]]; then
printf "%s\n" "Target size ${T_SIZE}MB is too small!" >&2
printf "%s %s\n" "Try values larger than" "${T_MINSIZE}MB" >&2
exit 1
fi
# Set target audio bitrate
T_ARATE=$O_ARATE
# Calculate target video rate - MB -> KiB/s
T_VRATE=$(\
awk \
-v size="$T_SIZE" \
-v duration="$O_DUR" \
-v audio_rate="$O_ARATE" \
'BEGIN { print ( ( size * 8192.0 ) / ( 1.048576 * duration ) - audio_rate) }')
# Perform the conversion
ffmpeg.exe \
-y \
-i "${target}" \
-c:v libvpx-vp9 \
-c:a libopus \
-deadline good \
-quality good \
-cpu-used 0 \
-b:v "$T_VRATE"k \
-row-mt 1 \
-auto-alt-ref 6 \
-b:a "$T_ARATE"k \
-pass 1 \
-an \
-f webm \
NUL \
&& \
ffmpeg.exe \
-y \
-i "${target}" \
-c:v libvpx-vp9 \
-c:a libopus \
-deadline good \
-quality good \
-cpu-used 0 \
-b:v "$T_VRATE"k \
-row-mt 1 \
-auto-alt-ref 6 \
-b:a "$T_ARATE"k \
-pass 2 \
$T_FILE
}
function STDERR () {
printf "error?"
cat - 1>&2
}
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment