Last active
February 5, 2020 11:43
-
-
Save niosus/ba7f4d3729360aafc7ab946b3aa53229 to your computer and use it in GitHub Desktop.
High quality gif from video or images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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