mkgif

Earlier today, I posted this post:


Listening to Mike Oldfield - Tubular Bells currently.

The gif in that post I created from a video taken with my phone using ffmpeg and I really wasn't happy with the result. Which caused me to post this post:

I need some better settings to create a #gif from a #video… ffmpeg does alright but, just doing the ffmpeg -i video.mp4 -r 10 video.gif that I’ve been doing makes for some grainy gifs sometimes. It’s a simple and easy to remember command but, I know there has to be a better looking output…

After a bit of searching, I ran across this example and I wrote a bash script so I wouldn't have to try to remember the actual ffmpeg commands. It's still a work in progress but, I think the end result is somewhat better than the basic command I was using. See the end of this post for a couple of examples.

#!/bin/bash
# mkgif
# v 0.1 - 2016.03.08
#
# License: WTFPL2
#
# From example found here: http://superuser.com/a/556031
# also: http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
# ffmpeg -y -ss 30 -t 3 -i input.flv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
# ffmpeg -ss 30 -t 3 -i input.flv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
#
# Requirements:
#   ffmpeg
#   imagemagick

## DEFAULT OPTIONS ##
palette=/tmp/palette.png
output=/tmp/output.gif
fps=12
size=320
## END DEFAULT OPTIONS ##

USAGE(){
  cat << EOF
  usage: $(basename $0) options
  A wrapper script to convert a video file to a gif using ffmpeg
  OPTIONS:
    -h    Show this message

    REQUIRED:
    -i    Input file

    OPTIONAL:
    -b    Beginning position from start of video (in seconds)
    -f    FPS (default is 12 frames per second)
    -l    Length of gif (in seconds)
    -o    Optimize gif
    -s    Size of gif in width (default is 320 px)
EOF
}

while getopts "b:f:hi:l:os:" OPTION
do
  case $OPTION in
    b)
      if [[ $OPTARG ]]
        then
          begin="-ss $OPTARG"
        else
          begin=
      fi
      ;;
    f)
      fps=$OPTARG
      ;;
    i)
      input="$OPTARG"
      ;;
    h)
      USAGE
      ;;
    l)
      if [[ $OPTARG ]]
        then
          length="-t $OPTARG"
        else
          length=
      fi
      ;;
    o)
      opt=1
      ;;
    s)
      size="$OPTARG"
      ;;
  esac
done

shift $(($OPTIND -1))

OPTIMIZE(){
  echo ""
  echo Optimizing...
  convert -layers Optimize $output $input\.gif
}

CREATEGIF(){
  if [[ $input ]]
    then
      ffmpeg -y $begin $length -i $input -vf fps=$fps,scale=$size:-1:flags=lanczos,palettegen $palette
      ffmpeg -y -i $input -i $palette -filter_complex "fps=$fps,scale=$size:-1:flags=lanczos[x];[x][1:v]paletteuse" $begin $length $output
      if [[ $opt -eq 1 ]]
        then
          OPTIMIZE
        else
          cp $output $input\.gif
      fi
    else
      echo "Input file required!"
      echo ""
      USAGE
  fi
}

CREATEGIF

rm -f $palette $output

exit 0

The source can also be found on my Gogs instance.

record
Wes

And if anyone has any improvements you'd like to pass on to me regarding this, shoot me a message please.


Have a response to this post? Please use this link.