#!/usr/bin/env nix-shell
#! nix-shell -i bash -p ffmpeg gifsicle

# Uses ffmpeg to convert a video file to a gif file. Optimizes the final result
# with gifsicle.
#
# Requires: ffmpeg gifsicle
#
# Example:
#   vid2gif some-vid.mp4 output.gif
#   vid2gif -f 10 -s 00:00:10 -t 00:00:05 some-vid.mp4 output.gif

set -e
PALETTE="/tmp/palette.png"

usage() {
	cat <<EOL
Usage: ${0##*/} [-fsSth] SOURCE_FILE [destfile]

    -f [FPS]       set frames per second
    -s [hh:mm:ss]  set starting time (like -ss in ffmpeg)
    -S [W:H]       set width/height (either can be -1 for auto)
    -t [hh:mm:ss]  set the duration to capture (like -t in ffmpeg)
    -h             this help
EOL
}

cleanup() { rm -f "$PALETTE"; }
trap cleanup EXIT

#
fps=30
while getopts hf:s:t:S: opt; do
	case $opt in
	f) fps="$OPTARG" ;;
	s) start="-ss $OPTARG" ;;
	S) scale=",scale=$OPTARG:flags=lanczos" ;;
	t) duration="-t $OPTARG" ;;
	h)
		usage
		exit
		;;
	:)
		echo >&2 "$OPTARG requires an argument"
		usage
		exit 1
		;;
	*)
		echo >&2 "Not a valid arg: $opt"
		usage
		exit 1
		;;
	esac
done
shift $((OPTIND - 1))

#
if (($# == 0)); then
	echo >&2 "No movie file specified"
	exit
elif [[ ! -f $1 ]]; then
	echo >&2 "$1 does not exist"
	exit
fi

src="$1"
dest="${2:-${src%.*}.gif}"
flags="fps=${fps}$scale"

# stats_mode=full favors motion, causing the resulting palette to better
# accomodate fades and transitions.
ffmpeg -v warning $start $duration -i "file:$src" -vf "$flags,palettegen=stats_mode=full" -y "$PALETTE"
ffmpeg -v warning $start $duration -i "file:$src" -i "$PALETTE" -lavfi "$flags [x]; [x][1:v] paletteuse" -y "$dest"

gifsicle -O3 "$dest" -o "$dest"
