From 21637a606544b74458e9bf36acc5b71236bc57c7 Mon Sep 17 00:00:00 2001 From: Ira Abramov Date: Thu, 30 Nov 2017 13:06:58 +0200 Subject: [PATCH] GIF plugin: Added FPS auto-detection, support for filenames with spaces, and localized variables --- plugins/available/gif.plugin.bash | 61 ++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/plugins/available/gif.plugin.bash b/plugins/available/gif.plugin.bash index 443fbb28..d507f7d2 100644 --- a/plugins/available/gif.plugin.bash +++ b/plugins/available/gif.plugin.bash @@ -5,6 +5,7 @@ about-plugin 'video to gif helper functions' # Renamed gifify to v2gif to go avoid clobbering https://github.com/jclem/gifify # Requirements (Mac OS X using Homebrew): brew install ffmpeg giflossy imagemagick # Requirements on Ubuntu: sudo apt install ffmpeg imagemagick ; plus install https://github.com/pornel/giflossy +# Optional: install mediainfo for autodetection of original video FPS. # Optional: if lossy is not important, Ubuntu has gifsicle packaged for apt-get, instead of giflossy # Optional: gifski (from `brew install gifski` or github.com/ImageOptim/gifski) # for high quality huge files. @@ -17,7 +18,7 @@ function v2gif { param '4: -h ; Optional: high quality using gifski (installed seperately) - overrides "--lossy" above!' param '5: -d ; Optional: delete the original video file if succeeded' param '6: -t ; Optional: Tag the result with quality stamp for comparison use' - param '7: -f ; Optional: Change number of frames per second (default 10)' + param '7: -f ; Optional: Change number of frames per second (default 10 or original FPS if mediainfo installed)' param '8: -a ; Optional: Alert if resulting file is over kilobytes (default is 5000, 0 turns off)' example '$ v2gif foo.mov' example '$ v2gif foo.mov -w 600' @@ -26,17 +27,19 @@ function v2gif { example '$ v2gif -thw 600 *.avi *.mov' # Parse the options - args=$(getopt -l "alert:" -l "lossy:" -l "width:" -l del,delete -l high -l tag -l "fps:" -o "a:l:w:f:dht" -- "$@") + local args=$(getopt -l "alert:" -l "lossy:" -l "width:" -l del,delete -l high -l tag -l "fps:" -o "a:l:w:f:dht" -- "$@") - use_gifski="" - del_after="" - maxsize="" - lossiness="" - maxwidthski="" - giftagopt="" - giftag="" - fps=10 - alert=5000 + local use_gifski="" + local del_after="" + local maxsize="" + local lossiness="" + local maxwidthski="" + local giftagopt="" + local giftag="" + local defaultfps=10 + local infps="" + local fps="" + local alert=5000 eval set -- "$args" while [ $# -ge 1 ]; do case "$1" in @@ -47,7 +50,7 @@ function v2gif { ;; -d|--del|--delete) # Delete after - del_after=true + del_after="true" shift ;; -h|--high) @@ -88,7 +91,7 @@ function v2gif { done # Done Parsing, all that's left are the filenames - movies="$*" + local movies="$*" if [[ -z "$movies" ]]; then echo "$(tput setaf 1)No input files given. Example: v2gif file [file...] [-w ] [-l ] < $(tput sgr 0)" @@ -101,32 +104,46 @@ function v2gif { for file in $movies ; do - output_file="${file%.*}${giftag}.gif" + local output_file="${file%.*}${giftag}.gif" - echo "$(tput setaf 2)Creating $output_file ...$(tput sgr 0)" + # Set FPS to match the video if possible, otherwise fallback to default. + if [[ "$infps" ]] ; then + fps=$infps + else + fps=$defaultfps + if [[ -x /usr/bin/mediainfo ]] ; then + if /usr/bin/mediainfo "$file" | grep -q "Frame rate mode *: Variable" ; then + fps=$(/usr/bin/mediainfo "$file" | grep "Minimum frame rate" |sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1) + else + fps=$(/usr/bin/mediainfo "$file" | grep "Frame rate " |sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1) + fi + fi + fi + + echo "$(tput setaf 2)Creating '$output_file' at $fps FPS ...$(tput sgr 0)" if [[ "$use_gifski" = "true" ]] ; then # I trust @pornel to do his own resizing optimization choices - ffmpeg -loglevel panic -i $file -r $fps -vcodec png v2gif-tmp-%05d.png && \ - gifski $maxwidthski --fps $fps -o $output_file v2gif-tmp-*.png || return 2 + ffmpeg -loglevel panic -i "$file" -r $fps -vcodec png v2gif-tmp-%05d.png && \ + gifski $maxwidthski --fps $(printf "%.0f" $fps) -o "$output_file" v2gif-tmp-*.png || return 2 else - ffmpeg -loglevel panic -i $file $maxsize -r $fps -vcodec png v2gif-tmp-%05d.png && \ + ffmpeg -loglevel panic -i "$file" $maxsize -r $fps -vcodec png v2gif-tmp-%05d.png && \ convert +dither -layers Optimize v2gif-tmp-*.png GIF:- | \ - gifsicle $lossiness --no-warnings --colors 256 --delay=$((100/fps)) --loop --optimize=3 --multifile - > $output_file || return 2 + gifsicle $lossiness --no-warnings --colors 256 --delay=$(echo "100/$fps"|bc) --loop --optimize=3 --multifile - > "$output_file" || return 2 fi rm v2gif-tmp-*.png # Checking if the file is bigger than Twitter likes and warn if [[ $alert -gt 0 ]] ; then - out_size=$(wc --bytes < $output_file) + local out_size=$(wc --bytes < "$output_file") if [[ $out_size -gt $(( alert * 1000 )) ]] ; then - echo "$(tput setaf 3)Warning: $output_file is $((out_size/1000))kb, keeping $file even if --del requested.$(tput sgr 0)" + echo "$(tput setaf 3)Warning: '$output_file' is $((out_size/1000))kb, keeping '$file' even if --del requested.$(tput sgr 0)" del_after="" fi fi - [[ "$del_after" = "true" ]] && rm $file + [[ "$del_after" = "true" ]] && rm "$file" done