Skip to content

Instantly share code, notes, and snippets.

@earlgreyxxx
Created November 1, 2020 11:15
Show Gist options
  • Save earlgreyxxx/9ec077940a77c8689e4132099ad765fb to your computer and use it in GitHub Desktop.
Save earlgreyxxx/9ec077940a77c8689e4132099ad765fb to your computer and use it in GitHub Desktop.
#!/bin/sh
### capture image from movie file.
# defines default values
interval=60
bg=black
start=1
column=4
imagetype=png
vcodec=png
tile=
tiletype=jpg
crop=0+0
cut=
odir=.
leave=
if [ -n "$*" ] ; then
for arg in "$@"
do
eval `echo "$arg" | sed -r -n 's/^--(interval|bg|start|column|imagetype|vcodec|tile|tiletype|crop|cut|odir|leave)=(.+)$/\1=\"\2\"/p'`
done
eval moviepath=\$$#
fi
if [ -z "$moviepath" -o ! -e "$moviepath" ] ; then
cat << __EOS__ 1>&2
specified movie file is not exits.
usage: capture.sh <options> movie_file_path
options:
--start=1 :skip beginning second...
--odir=. :output directory path (no need last slash)
--interval=60 :interval seconds to capture
--crop=0+0 :crop pixels ( ex. 140+5 means crop top&bottom 140px,left&right 5px )
--imagetype=png :suffix for output capture image.(no need dot)
--vcodec=png :ffmpeg option for output capture vcodec
--tile= :each pixel width of capture images if you want.
--tiletype=jpg :output tiled image type
--bg=black :background color if -tile is specied
--column=4 :column nums if -tile is specied
--cut= :y means throw away the last remaindered images when tile is available
--leave= :y means leave thumbnail files when tile is specified
__EOS__
exit 1
fi
if [ ! -d "$odir" ]; then
mkdir -p "$odir"
fi
odir=${odir}/caps.$$
mkdir -p "$odir"
info=`ffprobe -show_streams "$moviepath" 2> /dev/null | sed -n -r '/^(duration|width|height|display_aspect_ratio)=/p'`
duration=`echo $info | grep -oP '(?<=duration=)\d+' | head -n 1`
if [ -z "$duration" ] ; then
evalstr=`ffprobe "$moviepath" 2>&1 | sed -n -r 's/^.*Duration: ([0-9]+):([0-9]+):([0-9]+).*$/eval expr \1 \\\* 3600 + \2 \\\* 60 + \3/p'`
duration=`$evalstr`
fi
mwidth=`echo $info | grep -oP '(?<=width=)\d+' | head -n 1`
mheight=`echo $info | grep -oP '(?<=height=)\d+' | head -n 1`
aspect=`echo $info | grep -oP '(?<=display_aspect_ratio=)\d+:\d+'`
aw=`echo $aspect | sed -r 's/([0-9]+):([0-9]+)/\1/'`
ah=`echo $aspect | sed -r 's/([0-9]+):([0-9]+)/\2/'`
if [ $aw -gt 0 -a $ah -gt 0 ] ; then
mwidth=`expr $mheight \* $aw \/ $ah`
fi
if [ "$start" -gt "$duration" ] ; then
echo skip seconds over duration... 1>&2
exit 1
fi
echo -n "Input end point(default $duration): "
read cin
if [ -n "$cin" ]; then
if expr $cin + 1 > /dev/null 2>&1 ; then duration=$cin; fi
fi
if [ "$duration" -lt "$start" ] ; then
echo end seconds letter than start second... 1>&2
exit 1
fi
cropw=`echo $crop | sed -n -r 's/^([0-9]+)\+([0-9]+)$/\2/p'`
croph=`echo $crop | sed -n -r 's/^([0-9]+)\+([0-9]+)$/\1/p'`
crop=`echo $crop | sed -n -r '/^[0-9]+$/p'`
if [ -z "$cropw" -a -z "$croph" -a -n "$crop" ] ; then
croph="$crop"
fi
if [ -z "$cropw" ] ; then cropw=0 ; fi
if [ -z "$croph" ] ; then croph=0 ; fi
crop_mheight=$mheight
if [ $croph -gt 0 ] ; then
crop_mheight=`expr $mheight - 2 \* $croph`
fi
crop_mwidth=$mwidth
if [ $cropw -gt 0 ] ; then
crop_mwidth=`expr $mwidth - 2 \* $cropw`
fi
if [ $cropw -gt 0 -o $croph -gt 0 ] ; then
geometry=${crop_mwidth}x${crop_mheight}+${cropw}+${croph}
fi
movieext=`echo "$moviepath" | grep -Eo '\..+$'`
moviebase=`basename "$moviepath" "$movieext"`
for i in `seq $start $interval $duration`; do
thumbfile=`printf "${odir}/%s-%05d.${imagetype}" "$moviebase" $i`
ffmpeg -y -v error -ss $i -i "$moviepath" -vframes 1 -vcodec $vcodec -s ${mwidth}x${mheight} "$thumbfile"
if [ -n "$geometry" ] ; then
mogrify -crop $geometry "$thumbfile"
fi
echo Generated $thumbfile ... 2>&1
done
echo Generated thumbnails done.
if [ -n "$tile" ] ; then
srcfiles=$(find "${odir}" -type f -name "${moviebase}*.${imagetype}" | sed -e 's/^/"/' -e 's/$/"/')
filenum=$(echo "$srcfiles" | wc -l)
if [ "$cut" = "y" ] ; then
cutnum=$(expr $filenum % $column)
if [ $cutnum -ne 0 ] ; then
srcfiles=$(echo "$srcfiles" | head -n -$cutnum)
filenum=$(expr $filenum - $cutnum)
fi
fi
tmptile="/tmp/tmp-tile-image.$$.$tiletype"
thumfiles=$(echo $srcfiles)
eval montage $thumfiles -geometry ${tile}x+0+0 -tile ${column}x -background $bg -monitor $tmptile
mv $tmptile "${odir}/../${moviebase}.$tiletype"
if [ "$leave" != 'y' ] ; then
echo deleting $odir ... 1>&2
rm -fr "$odir"
exit 0
fi
fi
mv "$odir" "${odir}/../${moviebase}_$$"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment