#!/usr/bin/env bash declare usage usage="Usage: $(basename "$0") [-h] $(basename "$0") [FPS] Creates a gif from a video file. command line arguments: - the path to the movie we're converting - the start time of the finished gif - duration; the length of the video clip after the start time to convert Time(s) can be in seconds, or it also accepts the \"hh:mm:ss[.xxx]\" format [FPS] - (optional) specify an integer fps value. default is 10 For best output, it should be a factor of 100; e.g. 10, 20, 25, 50 e.g. gifme ~/Movies/your-favorite-movie.mp4 00:43:04 5 e.g. gifme ~/Movies/your-favorite-movie.mp4 01:04:02 10.5 25 Note if you want to convert the entire duration for a video file to a gif, you can provide a duration much higher than the length of the video e.g. gifme ~/Movies/a-short-video.mkv 0 9999999 10 requires 'imagemagick' and 'ffmpeg' Modified from: https://github.com/holman/dotfiles/blob/master/bin/movieme " # print help if user asked for it if [[ "$1" =~ ^[-]{1,2}?h(elp)?$ ]]; then echo "${usage}" exit 0 fi havecmd -v ffmpeg || exit $? havecmd -V 'This is typically installed as part of imagemagick' magick || exit $? # quit if ffmpeg fails set -e # reset temp directory tdir="$(mktemp -d)" main() { # check for command line arguments if [[ -z "$3" ]]; then printf "You didn't provide enough arguments. Type 'gifme -h' for additional help. \$1 - the path to the movie we're converting \$2 - the start time of the finished gif \$3 - duration; the length of the video clip after the start time to convert Time(s) can be in seconds, or it also accepts the \"hh:mm:ss[.xxx]\" format \$4 - (optional) specify an integer fps value. default is 10 For best output, it should be a factor of 100; e.g. 10, 20, 25, 50 " return 1 fi # process fps arg readonly fps="${4:-10}" readonly convert_delay="$((100 / fps))" # generate output filename based on input file declare output_filename current_time current_time="$(date +%H.%M.%S)" output_filename="$(basename "$1")" output_filename="${output_filename%.*}" # remove extension output_filename="${output_filename}-gifme-${current_time}.gif" # create frames # i - input # f - force image format # ss - start time # t - time # r - fps ffmpeg -i "$1" -f image2 -ss "$2" -t "$3" -r "$fps" /tmp/gifme/d-%09d.png printf "Converting %d frames to a gif...\n" "$(find /tmp/gifme | wc -l)" # convert to gif # delay - speed, determined by fps above # loop 0 - make gif repeat itself magick -delay "${convert_delay}" -loop 0 -limit memory 2GB -limit map 2GB /tmp/gifme/*.png "${output_filename}" printf "Created %s successfully\n" "${output_filename}" } main "$@" ret=$? rm -rf "$tdir" exit "$ret"