Merge pull request #2014 from gaelicWizard/plugin/gif
plugin/GIF: use `type -p` and lintpull/1958/head
commit
af801cfadc
|
|
@ -90,6 +90,7 @@ plugins/available/cmd-returned-notify.plugin.bash
|
||||||
plugins/available/direnv.plugin.bash
|
plugins/available/direnv.plugin.bash
|
||||||
plugins/available/dirs.plugin.bash
|
plugins/available/dirs.plugin.bash
|
||||||
plugins/available/docker-machine.plugin.bash
|
plugins/available/docker-machine.plugin.bash
|
||||||
|
plugins/available/gif.plugin.bash
|
||||||
plugins/available/git-subrepo.plugin.bash
|
plugins/available/git-subrepo.plugin.bash
|
||||||
plugins/available/git.plugin.bash
|
plugins/available/git.plugin.bash
|
||||||
plugins/available/go.plugin.bash
|
plugins/available/go.plugin.bash
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
cite about-plugin
|
# shellcheck shell=bash
|
||||||
about-plugin 'video to gif, gif to WebM helper functions'
|
about-plugin 'video to gif, gif to WebM helper functions'
|
||||||
|
|
||||||
# Based loosely on:
|
# Based loosely on:
|
||||||
|
|
@ -12,7 +12,7 @@ about-plugin 'video to gif, gif to WebM helper functions'
|
||||||
# Optional: if lossy is not important, Ubuntu has gifsicle packaged for apt-get, instead of giflossy
|
# 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)
|
# Optional: gifski (from `brew install gifski` or github.com/ImageOptim/gifski)
|
||||||
# for high quality huge files.
|
# for high quality huge files.
|
||||||
function v2gif {
|
function v2gif() {
|
||||||
about 'Converts a .mov/.avi/.mp4 file into an into an animated GIF.'
|
about 'Converts a .mov/.avi/.mp4 file into an into an animated GIF.'
|
||||||
group 'gif'
|
group 'gif'
|
||||||
param '1: MOV/AVI/MP4 file name(s)'
|
param '1: MOV/AVI/MP4 file name(s)'
|
||||||
|
|
@ -30,25 +30,44 @@ function v2gif {
|
||||||
example '$ v2gif -dh *.avi'
|
example '$ v2gif -dh *.avi'
|
||||||
example '$ v2gif -thw 600 *.avi *.mov'
|
example '$ v2gif -thw 600 *.avi *.mov'
|
||||||
|
|
||||||
local convert=$(which convert) ; [[ -x "$convert" ]] || { echo "No convert found!" ; return 2 ;}
|
local convert ffmpeg mediainfo gifsicle getopt args gifski out_size
|
||||||
local ffmpeg=$(which ffmpeg) ; [[ -x "$ffmpeg" ]] || { echo "No ffmpeg found!" ; return 2 ;}
|
|
||||||
local mediainfo=$(which mediainfo) ; [[ -x "$mediainfo" ]] || { echo "No mediainfo found!" ; return 2 ;}
|
|
||||||
local gifsicle=$(which gifsicle) ; [[ -x "$gifsicle" ]] || { echo "No gifsicle found!" ; return 2 ;}
|
|
||||||
local getopt=$(which getopt)
|
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]] ; then
|
convert="$(type -p convert)"
|
||||||
|
[[ -x "$convert" ]] || {
|
||||||
|
echo "No convert found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
ffmpeg="$(type -p ffmpeg)"
|
||||||
|
[[ -x "$ffmpeg" ]] || {
|
||||||
|
echo "No ffmpeg found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
mediainfo="$(type -p mediainfo)"
|
||||||
|
[[ -x "$mediainfo" ]] || {
|
||||||
|
echo "No mediainfo found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
gifsicle="$(type -p gifsicle)"
|
||||||
|
[[ -x "$gifsicle" ]] || {
|
||||||
|
echo "No gifsicle found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
getopt="$(type -p getopt)"
|
||||||
|
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
# Getopt on BSD is incompatible with GNU
|
# Getopt on BSD is incompatible with GNU
|
||||||
getopt=/usr/local/opt/gnu-getopt/bin/getopt
|
getopt=/usr/local/opt/gnu-getopt/bin/getopt
|
||||||
[[ -x "$getopt" ]] || { echo "No GNU-getopt found!" ; return 2 ;}
|
[[ -x "$getopt" ]] || {
|
||||||
|
echo "No GNU-getopt found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Parse the options
|
# Parse the options
|
||||||
local args=$($getopt -l "alert:" -l "lossy:" -l "width:" -l del,delete -l high -l tag -l "fps:" -l webm -o "a:l:w:f:dhmt" -- "$@")
|
args=$("$getopt" -l "alert:" -l "lossy:" -l "width:" -l del,delete -l high -l tag -l "fps:" -l webm -o "a:l:w:f:dhmt" -- "$@") || {
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo 'Terminating...' >&2
|
echo 'Terminating...' >&2
|
||||||
return 2
|
return 2
|
||||||
fi
|
}
|
||||||
|
|
||||||
eval set -- "$args"
|
eval set -- "$args"
|
||||||
local use_gifski=""
|
local use_gifski=""
|
||||||
|
|
@ -63,54 +82,58 @@ function v2gif {
|
||||||
local fps=""
|
local fps=""
|
||||||
local make_webm=""
|
local make_webm=""
|
||||||
local alert=5000
|
local alert=5000
|
||||||
while [ $# -ge 1 ]; do
|
while [[ $# -ge 1 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--)
|
--)
|
||||||
# No more options left.
|
# No more options left.
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
-d|--del|--delete)
|
-d | --del | --delete)
|
||||||
# Delete after
|
# Delete after
|
||||||
opt_del_after="true"
|
opt_del_after="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-h|--high)
|
-h | --high)
|
||||||
#High Quality, use gifski
|
#High Quality, use gifski
|
||||||
local gifski=$(which gifski) ; [[ -x "$gifski" ]] || { echo "No gifski found!" ; return 2 ; }
|
gifski="$(type -p gifski)"
|
||||||
|
[[ -x "$gifski" ]] || {
|
||||||
|
echo "No gifski found!"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
use_gifski=true
|
use_gifski=true
|
||||||
giftag="${giftag}-h"
|
giftag="${giftag}-h"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-w|--width)
|
-w | --width)
|
||||||
maxsize="-vf scale=$2:-1"
|
maxsize="-vf scale=$2:-1"
|
||||||
maxwidthski="-W $2"
|
maxwidthski="-W $2"
|
||||||
giftag="${giftag}-w$2"
|
giftag="${giftag}-w$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-t|--tag)
|
-t | --tag)
|
||||||
# mark with a quality tag
|
# mark with a quality tag
|
||||||
giftagopt="true"
|
giftagopt="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-l|--lossy)
|
-l | --lossy)
|
||||||
# Use giflossy parameter
|
# Use giflossy parameter
|
||||||
lossiness="--lossy=$2"
|
lossiness="--lossy=$2"
|
||||||
giftag="${giftag}-l$2"
|
giftag="${giftag}-l$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-f|--fps)
|
-f | --fps)
|
||||||
# select fps
|
# select fps
|
||||||
infps="$2"
|
infps="$2"
|
||||||
giftag="${giftag}-f$2"
|
giftag="${giftag}-f$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-a|--alert)
|
-a | --alert)
|
||||||
# set size alert
|
# set size alert
|
||||||
alert="$2"
|
alert="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-m|--webm)
|
-m | --webm)
|
||||||
# set size alert
|
# set size alert
|
||||||
make_webm="true"
|
make_webm="true"
|
||||||
shift
|
shift
|
||||||
|
|
@ -135,47 +158,47 @@ function v2gif {
|
||||||
[[ -z "$giftag" ]] && giftag="-default"
|
[[ -z "$giftag" ]] && giftag="-default"
|
||||||
[[ -z "$giftagopt" ]] && giftag=""
|
[[ -z "$giftagopt" ]] && giftag=""
|
||||||
|
|
||||||
for file ; do
|
for file; do
|
||||||
|
|
||||||
local output_file="${file%.*}${giftag}.gif"
|
local output_file="${file%.*}${giftag}.gif"
|
||||||
local del_after=$opt_del_after
|
local del_after=$opt_del_after
|
||||||
|
|
||||||
if [[ "$make_webm" ]] ; then
|
if [[ -n "$make_webm" ]]; then
|
||||||
$ffmpeg -loglevel panic -i "$file" \
|
$ffmpeg -loglevel panic -i "$file" \
|
||||||
-c:v libvpx -crf 4 -threads 0 -an -b:v 2M -auto-alt-ref 0 \
|
-c:v libvpx -crf 4 -threads 0 -an -b:v 2M -auto-alt-ref 0 \
|
||||||
-quality best -loop 0 "${file%.*}.webm" || return 2
|
-quality best -loop 0 "${file%.*}.webm" || return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set FPS to match the video if possible, otherwise fallback to default.
|
# Set FPS to match the video if possible, otherwise fallback to default.
|
||||||
if [[ "$infps" ]] ; then
|
if [[ -n "$infps" ]]; then
|
||||||
fps=$infps
|
fps=$infps
|
||||||
else
|
else
|
||||||
fps=$defaultfps
|
fps=$defaultfps
|
||||||
if [[ -x $mediainfo ]] ; then
|
if [[ -x "$mediainfo" ]]; then
|
||||||
fps=$($mediainfo "$file" | grep "Frame rate " |sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1)
|
fps=$($mediainfo "$file" | grep "Frame rate " | sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1)
|
||||||
[[ -z "$fps" ]] && fps=$($mediainfo "$file" | grep "Minimum frame rate" |sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1)
|
[[ -z "$fps" ]] && fps=$($mediainfo "$file" | grep "Minimum frame rate" | sed 's/.*: \([0-9.]\+\) .*/\1/' | head -1)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$(tput setaf 2)Creating '$output_file' at $fps FPS ...$(tput sgr 0)"
|
echo "$(tput setaf 2)Creating '$output_file' at $fps FPS ...$(tput sgr 0)"
|
||||||
|
|
||||||
if [[ "$use_gifski" = "true" ]] ; then
|
if [[ "$use_gifski" = "true" ]]; then
|
||||||
# I trust @pornel to do his own resizing optimization choices
|
# I trust @pornel to do his own resizing optimization choices
|
||||||
$ffmpeg -loglevel panic -i "$file" -r $fps -vcodec png v2gif-tmp-%05d.png && \
|
$ffmpeg -loglevel panic -i "$file" -r "$fps" -vcodec png v2gif-tmp-%05d.png \
|
||||||
$gifski v2gif-tmp-*.png $maxwidthski --fps $(printf "%.0f" $fps) -o "$output_file" || return 2
|
&& $gifski v2gif-tmp-*.png "$maxwidthski" --fps "$(printf "%.0f" "$fps")" -o "$output_file" || return 2
|
||||||
else
|
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:- | \
|
&& $convert +dither -layers Optimize v2gif-tmp-*.png GIF:- \
|
||||||
$gifsicle $lossiness --no-warnings --colors 256 --delay=$(echo "100/$fps"|bc) --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
|
fi
|
||||||
|
|
||||||
rm v2gif-tmp-*.png
|
rm v2gif-tmp-*.png
|
||||||
|
|
||||||
# Checking if the file is bigger than Twitter likes and warn
|
# Checking if the file is bigger than Twitter likes and warn
|
||||||
if [[ $alert -gt 0 ]] ; then
|
if [[ $alert -gt 0 ]]; then
|
||||||
local out_size=$(wc --bytes < "$output_file")
|
out_size=$(wc --bytes < "$output_file")
|
||||||
if [[ $out_size -gt $(( alert * 1000 )) ]] ; then
|
if [[ $out_size -gt $((alert * 1000)) ]]; then
|
||||||
echo "$(tput setaf 3)Warning: '$output_file' is $((out_size/1000))kb.$(tput sgr 0)"
|
echo "$(tput setaf 3)Warning: '$output_file' is $((out_size / 1000))kb.$(tput sgr 0)"
|
||||||
[[ "$del_after" == "true" ]] && echo "$(tput setaf 3)Warning: Keeping '$file' even though --del requested.$(tput sgr 0)"
|
[[ "$del_after" == "true" ]] && echo "$(tput setaf 3)Warning: Keeping '$file' even though --del requested.$(tput sgr 0)"
|
||||||
del_after=""
|
del_after=""
|
||||||
fi
|
fi
|
||||||
|
|
@ -201,13 +224,13 @@ function any2webm() {
|
||||||
example '$ any2webm foo.gif'
|
example '$ any2webm foo.gif'
|
||||||
example '$ any2webm *.mov -b 1.5M -s 600x480'
|
example '$ any2webm *.mov -b 1.5M -s 600x480'
|
||||||
|
|
||||||
# Parse the options
|
local args out_size
|
||||||
local args=$(getopt -l alert -l "bandwidth:" -l "width:" -l del,delete -l tag -l "fps:" -l webm -o "a:b:w:f:dt" -- "$@")
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
# Parse the options
|
||||||
|
args=$(getopt -l alert -l "bandwidth:" -l "width:" -l del,delete -l tag -l "fps:" -l webm -o "a:b:w:f:dt" -- "$@") || {
|
||||||
echo 'Terminating...' >&2
|
echo 'Terminating...' >&2
|
||||||
return 2
|
return 2
|
||||||
fi
|
}
|
||||||
|
|
||||||
eval set -- "$args"
|
eval set -- "$args"
|
||||||
local opt_del_after=""
|
local opt_del_after=""
|
||||||
|
|
@ -218,41 +241,41 @@ function any2webm() {
|
||||||
local fps=""
|
local fps=""
|
||||||
local bandwidth="2M"
|
local bandwidth="2M"
|
||||||
local alert=5000
|
local alert=5000
|
||||||
while [ $# -ge 1 ]; do
|
while [[ $# -ge 1 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--)
|
--)
|
||||||
# No more options left.
|
# No more options left.
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
-d|--del|--delete)
|
-d | --del | --delete)
|
||||||
# Delete after
|
# Delete after
|
||||||
opt_del_after="true"
|
opt_del_after="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-s|--size)
|
-s | --size)
|
||||||
size="-s $2"
|
size="-s $2"
|
||||||
webmtag="${webmtag}-s$2"
|
webmtag="${webmtag}-s$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-t|--tag)
|
-t | --tag)
|
||||||
# mark with a quality tag
|
# mark with a quality tag
|
||||||
webmtagopt="true"
|
webmtagopt="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-f|--fps)
|
-f | --fps)
|
||||||
# select fps
|
# select fps
|
||||||
fps="-r $2"
|
fps="-r $2"
|
||||||
webmtag="${webmtag}-f$2"
|
webmtag="${webmtag}-f$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-b|--bandwidth)
|
-b | --bandwidth)
|
||||||
# select bandwidth
|
# select bandwidth
|
||||||
bandwidth="$2"
|
bandwidth="$2"
|
||||||
webmtag="${webmtag}-b$2"
|
webmtag="${webmtag}-b$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-a|--alert)
|
-a | --alert)
|
||||||
# set size alert
|
# set size alert
|
||||||
alert="$2"
|
alert="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
@ -269,7 +292,7 @@ function any2webm() {
|
||||||
[[ -z "$webmtag" ]] && webmtag="-default"
|
[[ -z "$webmtag" ]] && webmtag="-default"
|
||||||
[[ -z "$webmtagopt" ]] && webmtag=""
|
[[ -z "$webmtagopt" ]] && webmtag=""
|
||||||
|
|
||||||
for file ; do
|
for file; do
|
||||||
|
|
||||||
local output_file="${file%.*}${webmtag}.webm"
|
local output_file="${file%.*}${webmtag}.webm"
|
||||||
local del_after=$opt_del_after
|
local del_after=$opt_del_after
|
||||||
|
|
@ -277,14 +300,14 @@ function any2webm() {
|
||||||
echo "$(tput setaf 2)Creating '$output_file' ...$(tput sgr 0)"
|
echo "$(tput setaf 2)Creating '$output_file' ...$(tput sgr 0)"
|
||||||
|
|
||||||
$ffmpeg -loglevel panic -i "$file" \
|
$ffmpeg -loglevel panic -i "$file" \
|
||||||
-c:v libvpx -crf 4 -threads 0 -an -b:v $bandwidth -auto-alt-ref 0 \
|
-c:v libvpx -crf 4 -threads 0 -an -b:v "$bandwidth" -auto-alt-ref 0 \
|
||||||
-quality best $fps $size -loop 0 -pix_fmt yuva420p "$output_file" || return 2
|
-quality best "$fps" "$size" -loop 0 -pix_fmt yuva420p "$output_file" || return 2
|
||||||
|
|
||||||
# Checking if the file is bigger than Twitter likes and warn
|
# Checking if the file is bigger than Twitter likes and warn
|
||||||
if [[ $alert -gt 0 ]] ; then
|
if [[ $alert -gt 0 ]]; then
|
||||||
local out_size=$(wc --bytes < "$output_file")
|
out_size=$(wc --bytes < "$output_file")
|
||||||
if [[ $out_size -gt $(( alert * 1000 )) ]] ; then
|
if [[ $out_size -gt $((alert * 1000)) ]]; then
|
||||||
echo "$(tput setaf 3)Warning: '$output_file' is $((out_size/1000))kb.$(tput sgr 0)"
|
echo "$(tput setaf 3)Warning: '$output_file' is $((out_size / 1000))kb.$(tput sgr 0)"
|
||||||
[[ "$del_after" == "true" ]] && echo "$(tput setaf 3)Warning: Keeping '$file' even though --del requested.$(tput sgr 0)"
|
[[ "$del_after" == "true" ]] && echo "$(tput setaf 3)Warning: Keeping '$file' even though --del requested.$(tput sgr 0)"
|
||||||
del_after=""
|
del_after=""
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue