2019-08-06 10:56:54 -07:00
|
|
|
#!/usr/bin/env nix-shell
|
|
|
|
#! nix-shell -i bash -p ffmpeg gifsicle
|
2016-05-31 21:26:43 -07:00
|
|
|
|
2017-05-10 01:25:11 -07:00
|
|
|
# Uses ffmpeg to convert a video file to a gif file. Optimizes the final result
|
|
|
|
# with gifsicle.
|
|
|
|
#
|
2020-02-08 20:26:11 -08:00
|
|
|
# Requires: ffmpeg gifsicle
|
2017-05-10 01:25:11 -07:00
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
# vid2gif some-vid.mp4 output.gif
|
|
|
|
# vid2gif -f 10 -s 00:00:10 -t 00:00:05 some-vid.mp4 output.gif
|
2016-11-08 18:38:26 -08:00
|
|
|
|
2020-02-08 20:26:11 -08:00
|
|
|
shift # Get rid of extraneous nix-shell argument
|
|
|
|
|
2017-05-10 01:25:11 -07:00
|
|
|
set -e
|
|
|
|
PALETTE="/tmp/palette.png"
|
|
|
|
|
|
|
|
usage() {
|
2017-12-05 22:39:10 -08:00
|
|
|
cat <<EOL
|
2017-07-03 07:36:15 -07:00
|
|
|
Usage: ${0##*/} [-fsSth] SOURCE_FILE [destfile]
|
2017-05-10 01:25:11 -07:00
|
|
|
|
|
|
|
-f [FPS] set frames per second
|
|
|
|
-s [hh:mm:ss] set starting time (like -ss in ffmpeg)
|
2017-05-10 05:33:09 -07:00
|
|
|
-S [W:H] set width/height (either can be -1 for auto)
|
2017-05-10 01:25:11 -07:00
|
|
|
-t [hh:mm:ss] set the duration to capture (like -t in ffmpeg)
|
|
|
|
-h this help
|
|
|
|
EOL
|
|
|
|
}
|
2016-05-31 21:26:43 -07:00
|
|
|
|
2017-05-10 01:25:11 -07:00
|
|
|
cleanup() { rm -f "$PALETTE"; }
|
|
|
|
trap cleanup EXIT
|
|
|
|
|
|
|
|
#
|
2016-11-08 18:38:26 -08:00
|
|
|
fps=30
|
2017-05-10 05:33:09 -07:00
|
|
|
while getopts hf:s:t:S: opt; do
|
2017-12-05 22:39:10 -08:00
|
|
|
case $opt in
|
|
|
|
f) fps="$OPTARG" ;;
|
|
|
|
s) start="-ss $OPTARG" ;;
|
|
|
|
S) scale=",scale=$OPTARG:flags=lanczos" ;;
|
|
|
|
t) duration="-t $OPTARG" ;;
|
|
|
|
h) usage
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
:) >&2 echo "$OPTARG requires an argument"
|
|
|
|
usage
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
*) >&2 echo "Not a valid arg: $opt"
|
|
|
|
usage
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
2016-11-08 18:38:26 -08:00
|
|
|
done
|
2017-05-10 01:25:11 -07:00
|
|
|
shift $((OPTIND-1))
|
|
|
|
|
|
|
|
#
|
|
|
|
if (($# == 0)); then
|
2017-12-05 22:39:10 -08:00
|
|
|
>&2 echo "No movie file specified"
|
|
|
|
exit
|
2017-05-10 01:25:11 -07:00
|
|
|
elif [[ ! -f $1 ]]; then
|
2017-12-05 22:39:10 -08:00
|
|
|
>&2 echo "$1 does not exist"
|
|
|
|
exit
|
2017-05-10 01:25:11 -07:00
|
|
|
fi
|
2016-11-08 18:38:26 -08:00
|
|
|
|
2017-05-10 01:25:11 -07:00
|
|
|
src="$1"
|
2017-05-10 05:33:09 -07:00
|
|
|
dest="${2:-${src%.*}.gif}"
|
|
|
|
flags="fps=${fps}$scale"
|
2016-05-31 21:26:43 -07:00
|
|
|
|
2017-05-10 01:25:11 -07:00
|
|
|
# stats_mode=full favors motion, causing the resulting palette to better
|
|
|
|
# accomodate fades and transitions.
|
|
|
|
ffmpeg -v warning $start $duration -i "$src" -vf "$flags,palettegen=stats_mode=full" -y "$PALETTE"
|
|
|
|
ffmpeg -v warning $start $duration -i "$src" -i "$PALETTE" -lavfi "$flags [x]; [x][1:v] paletteuse" -y "$dest"
|
2016-05-31 21:26:43 -07:00
|
|
|
|
2019-08-06 10:56:54 -07:00
|
|
|
gifsicle -O3 "$dest" -o "$dest"
|