Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@tomasdev
Last active September 3, 2020 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomasdev/ed7e27066d0316bb3ef210e13278831e to your computer and use it in GitHub Desktop.
Save tomasdev/ed7e27066d0316bb3ef210e13278831e to your computer and use it in GitHub Desktop.
Video to GIF converter (uses ffmpeg)
#!/bin/bash
printable_colours=256
# DEFAULTS
SIZE=480
FPS=15
LENGTH=2
# Report usage
usage() {
echo "
ℹ️ Usage:
$(basename $0) [options] [--] file.ext
Options:
--size, -s
Maximum width or height of the output in pixels (Default: 480)
--fps, -f
Frames per second (Default: 15)
--length, -l
Length of the output in seconds (Default: 2)"
# Optionally exit with a status code
if [ -n "$1" ]; then
exit "$1"
fi
}
invalid() {
echo
echo "❌ Error: Unrecognized argument: $1 🧐" >&2
usage 1
}
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
ARGV=()
END_OF_OPT=
while [[ $# -gt 0 ]]; do
arg="$1"; shift
case "${END_OF_OPT}${arg}" in
--) ARGV+=("$arg"); END_OF_OPT=1 ;;
--*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
--*) ARGV+=("$arg"); END_OF_OPT=1 ;;
-*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
*) ARGV+=("$arg") ;;
esac
done
# Apply pre-processed options
set -- "${ARGV[@]}"
# Parse options
END_OF_OPT=
POSITIONAL=()
while [[ $# -gt 0 ]]; do
case "${END_OF_OPT}${1}" in
-h|--help) usage 0 ;;
-s|--size) shift; SIZE="$1" ;;
-f|--fps) shift; FPS="$1" ;;
-l|--length) shift; LENGTH="$1" ;;
# -q|--quiet) QUIET=1 ;;
--) END_OF_OPT=1 ;;
-*) invalid "$1" ;;
*) POSITIONAL+=("$1") ;;
esac
shift
done
# Restore positional parameters
set -- "${POSITIONAL[@]}"
if [ ${#POSITIONAL[@]} != 1 ]; then
echo
echo "❌ Error: too many arguments 😩"
usage 1
fi
FILE=$POSITIONAL
if [ ! -f $FILE ]; then
echo
echo "❌ Error: file $FILE does not exist 🤔"
exit 1
fi
FILE_NAME=`echo $FILE | cut -d'.' -f1`
if [ -f "$FILE_NAME.gif" ]; then
echo
echo "❌ Error: file $FILE_NAME.gif already exists 😭"
exit 1
fi
COLOR_BLUE="\e[34m"
COLOR_CYAN="\e[36m"
COLOR_CYAN_BG="\e[46m\e[30m"
COLOR_RESET="\e[00m"
ORIG_FILE=$(basename $FILE)
DEST_FILE=`echo $ORIG_FILE | cut -d'.' -f1`
MESSAGE="Converting $COLOR_CYAN$ORIG_FILE$COLOR_RESET to $COLOR_BLUE$DEST_FILE.gif$COLOR_RESET"
spinners=("🕛" "🕐" "🕑" "🕒" "🕓" "🕔" "🕕" "🕖" "🕗" "🕘" "🕙" "🕚")
monkeys=("🙈" "🙉" "🙊")
echo
ffmpeg -t $LENGTH -hide_banner -loglevel panic -i $FILE -filter_complex "[0:v] fps=$FPS,scale=$SIZE:$SIZE:force_original_aspect_ratio=decrease,split [a][b];[a] palettegen [p];[b][p] paletteuse" $FILE_NAME.gif & PID=$!
j=0
while kill -0 $PID 2> /dev/null
do
for i in "${spinners[@]}"
do
three_frames=$(( $(($j / 3)) % ${#monkeys[@]} ))
monkey=${monkeys[$three_frames]}
printf "\b\r$i$monkey $MESSAGE"
sleep 0.1
j=$(($j + 1))
done
done
printf "\b\r✅ Successfully created $COLOR_BLUE$FILE_NAME.gif$COLOR_RESET"
sleep 1
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment