Skip to content

Instantly share code, notes, and snippets.

@niosus
Last active February 5, 2020 11:43
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 niosus/ba7f4d3729360aafc7ab946b3aa53229 to your computer and use it in GitHub Desktop.
Save niosus/ba7f4d3729360aafc7ab946b3aa53229 to your computer and use it in GitHub Desktop.
High quality gif from video or images
#!/bin/bash
FPS=10 # Default value, is updated later on.
WIDTH=900 # Default value, is updated later on.
COLORS=256 # Default value, is updated later on.
OUTPUT=''
VIDEO=''
IMAGE_MASK=''
BASE_INPUT_NAME=''
SPEED='1'
OVERWRITE=''
KEEP_TEMPORARY_FILES=''
show_intro_message () {
echo ""
echo "This script converts video/images to a compact high quality gif."
echo ""
echo "Example usages that produce 'test.gif' file:"
echo " 1) ./to_gif.sh -v test.mp4 -f 10 -w 600 -y -s 2"
echo " 2) ./to_gif.sh -i test_%05d.png -o test.gif -f 10 -w 600 -y"
echo ""
}
show_help_message () {
echo ""
echo "The script supports the following flags:"
echo " -v VIDEO Input video file name"
echo " -i IMAGE_MASK Input images mask, e.g. images_%05d.png"
echo " -o OUTPUT Output file name"
echo " -f FPS What fps should be used for gif"
echo " -w WIDTH Width of the gif. Height will be auto adjusted"
echo " -s SPEED Speed modifier ('-s 2' will make the gif twice faster)"
echo " -k KEEP_TEMP Keep temporary files after the script exits"
echo " -c COLORS Amount of colors to use in the pallette"
echo " -y Overwrite output files without prompt"
echo " -h Show this help and exit"
exit
}
show_error_message () {
echo ""
echo "ERROR: $1"
echo ""
show_help_message
}
if [ "$#" -le 1 ]; then
show_error_message "Not enough flags provided"
fi
# Parse flags
while getopts 'f:w:o:s:i:v:c:yhk' flag; do
case "${flag}" in
f) FPS=${OPTARG} ;;
w) WIDTH=${OPTARG} ;;
o) OUTPUT=${OPTARG} ;;
s) SPEED=${OPTARG} ;;
c) COLORS=${OPTARG} ;;
i) IMAGE_MASK=${OPTARG} ;;
v) VIDEO=${OPTARG} ;;
y) OVERWRITE='-y' ;;
k) KEEP_TEMPORARY_FILES='yes' ;;
h) show_intro_message && show_help_message ;;
*) show_error_message "Unexpected option ${flag}" ;;
esac
done
if [[ ${IMAGE_MASK} != '' ]] && [[ ${VIDEO} != '' ]]; then
show_error_message "You must provide EITHER -i or -v flags!"
exit
fi
if [[ ${OUTPUT} != '' ]]; then
BASE_INPUT_NAME=${OUTPUT%.*}
elif [[ ${VIDEO} != '' ]]; then
BASE_INPUT_NAME=${VIDEO%.*}
OUTPUT="${BASE_INPUT_NAME}.gif"
elif [[ ${IMAGE_MASK} != '' ]]; then
BASE_INPUT_NAME=$(echo ${IMAGE_MASK} | cut -d'.' -f1 | cut -d'%' -f1)
OUTPUT="${BASE_INPUT_NAME}.gif"
fi
if [[ ${VIDEO} != '' ]]; then echo "VIDEO = ${VIDEO}"; fi
if [[ ${IMAGE_MASK} != '' ]]; then echo "IMAGE_MASK = ${IMAGE_MASK}"; fi
echo "FPS = ${FPS}"
echo "WIDTH = ${WIDTH}"
echo "OUTPUT = ${OUTPUT}"
echo "SPEED = ${SPEED}x"
if [[ ${IMAGE_MASK} != '' ]]; then
# Generate a video from pngs
VIDEO="video_from_images_${BASE_INPUT_NAME}.mp4"
echo ""
echo "Generating temporary video: ${VIDEO}"
ffmpeg -hide_banner -loglevel panic -stats -f image2 -framerate ${FPS} \
-i ${IMAGE_MASK} ${VIDEO}
fi
# Create a palette
PALETTE="palette_${BASE_INPUT_NAME}.png"
echo ""
echo "Generating a pallette: ${PALETTE}"
ffmpeg -hide_banner -loglevel panic -stats ${OVERWRITE} -i ${VIDEO} -vf \
fps=${FPS},scale=${WIDTH}:-1:flags=lanczos,palettegen=stats_mode=diff,palettegen=max_colors=${COLORS} ${PALETTE}
# Generate gif from video using generated palette
echo ""
echo "Generating gif: ${OUTPUT}"
ffmpeg -hide_banner -loglevel panic -stats ${OVERWRITE} -i ${VIDEO} -i ${PALETTE} -an -filter_complex \
"setpts=PTS/${SPEED},fps=${FPS},scale=${WIDTH}:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle" ${OUTPUT}
if [[ ${KEEP_TEMPORARY_FILES} == '' ]]; then
echo ""
echo "Removing temporary pallette file: ${PALETTE}"
rm -f ${PALETTE}
if [[ ${IMAGE_MASK} != '' ]]; then
echo "Removing temporary video: ${VIDEO}"
rm -f ${VIDEO} # This is a temporary video generated from images.
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment