Subversion Repositories pub

Compare Revisions

No changes between revisions

Ignore whitespace Rev 282 → Rev 283

/video-contact-sheet/tags/1.0.4b/CHANGELOG
0,0 → 1,58
1.0.4b: (2007-04-17)
* Added error checks for failures to create vidcap or to process it
convert
* BUGFIX: Corrected error check on tempdir creation
* BUGFIX: Use temporary locations for temporary files (thanks to
Alon Levy).
* Aspect ratio support (might be buggy). Requires bc.
* Added $safe_rename_pattern to allow overriding the default alternate
naming when the output file exists
* Moved previous previous versions' changes to a separate file.
* Support for per-dir and system-wide configuration files. Precedence
in ascending order:
/etc/vcs.conf ~/.vcs.conf ./vcs.conf
* Added default_options (broken, currently ignored)
* BUGFIX: (Apparently) Corrected the one-vidcap-less/more bug
* Added codec ids of WMV9 and WMA3
 
1.0.3b: (2007-04-14)
* BUGFIX: Don't put the full video path in the heading
 
1.0.2b: (2007-04-14)
* Licensed under LGPL (was unlicensed before)
* Renamed variables and constants to me more congruent
* Added DEFAULT_COLS
* BUGFIX: Fixed program signature (broken in 1.0.1a)
* Streamlined error codes
* Added cleanup on failure and on delayed cleanup on success
* Changed default signature background to SlateGray (blue-ish gray)
 
1.0.1a: (2007-04-13)
* Print output filename
* Added manual mode (all timestamps provided by user)
* More flexible timestamp format (now e.g. 1h5 is allowed (means 1h 5secs)
* BUGFIX: Discard repeated timestamps
* Added "set -e". TODO: Add more verbose error messages when called
programs fail.
* Added basic support for a user configuration file.
 
1.0a: (2007-04-10)
* First release keeping track of history
* Put vcs' url in the signature
* Use system username in signature
* Added --shoehorn (you get the idea, right?) to feed extra commands to
the cappers. Lowelevel and not intended to be used anyway :P
* When just a vidcap is requested, take it from the middle of the video
* Added -H|--height
* Added codec ids of WMV8 and WMA2
 
0.99.1a: Interim version, renamed to 1.0a
 
0.99a:
* Added shadows
* More colourful headers
* Easier change of colours/fonts
 
0.5a: * First usable version
0.1: * First proof of concept
 
/video-contact-sheet/tags/1.0.4b/vcs
0,0 → 1,839
#!/bin/bash
#
# $Rev: 272 $ $Date: 2007-04-17 04:31:12 +0200 (dt, 17 abr 2007) $
#
# vcs
# Video Contact Sheet *NIX: Generates contact sheets (previews) of videos
#
# Copyright (C) 2007 Toni Corvera
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Author: Toni Corvera <outlyer@outlyer.net>
#
 
declare -r VERSION="1.0.4b"
#
# History (The full changelog was moved to a separate file and can be found
# at <http://p.outlyer.net/vcs/files/CHANGELOG>).
#
# 1.0.4b: (2007-04-17)
# * Added error checks for failures to create vidcap or to process it
# convert
# * BUGFIX: Corrected error check on tempdir creation
# * BUGFIX: Use temporary locations for temporary files (thanks to
# Alon Levy).
# * Aspect ratio support (might be buggy). Requires bc.
# * Added $safe_rename_pattern to allow overriding the default alternate
# naming when the output file exists
# * Moved previous previous versions' changes to a separate file.
# * Support for per-dir and system-wide configuration files. Precedence
# in ascending order:
# /etc/vcs.conf ~/.vcs.conf ./vcs.conf
# * Added default_options (broken, currently ignored)
# * BUGFIX: (Apparently) Corrected the one-vidcap-less/more bug
# * Added codec ids of WMV9 and WMA3
#
 
set -e
 
# Configuration file, please, use this file to modify the behaviour of the
# script. Using this allows overriding some variables (see below)
# to your liking. Only lines with a variable assignment are evaluated,
# it should follow bash syntax, note though that ';' can't be used
# currently in the variable values; e.g.:
#
# # Sample configuration for vcs
# user=myname # Sign all compositions as myname
# bg_heading=gray # Make the heading gray
#
# There is a total of three configuration files than are loaded if the exist:
# * /etc/vcs.conf: System wide conf, least precedence
# * $CFGFILE (by default ~/.vcs.conf): Per-user conf, second least precedence
# * ./vcs.conf: Per-dir confif, most precedence
#
# The variables that can be overriden are below the block of constants ahead.
declare -r CFGFILE=~/.vcs.conf
 
# Constants {{{
# see $decoder
declare -ri DEC_MPLAYER=1 DEC_FFMPEG=3
# See $timecode_from
declare -ri TC_INTERVAL=4 TC_NUMCAPS=8
# These can't be overriden, modify this line if you feel the need
declare -r PROGRAM_SIGNATURE="with Video Contact Sheet *NIX ${VERSION} <http://p.outlyer.net/vcs/>"
# see $safe_rename_pattern
declare -r DEFAULT_SAFE_REN_PATT="%b-%N.%e"
 
# }}} # End of constants
 
# Override-able variables {{{
 
declare -i DEFAULT_INTERVAL=300
declare -i DEFAULT_NUMCAPS=16
declare -i DEFAULT_COLS=2
# Text before the user name in the signature
declare user_signature="Preview created by"
# By default sign as the system's username
declare user=$(id -un)
# Which of the two methods should be used to guess the number of thumbnails
declare -i timecode_from=$TC_INTERVAL
# Which of the two vidcappers should be used (see -F, -M)
# mplayer seems to fail for mpeg or WMV9 files, at least on my system
declare -i decoder=$DEC_FFMPEG
# Options used in imagemagick, these options set the final aspect
# of the contact sheet
declare output_format=png # ImageMagick decides the type from the extension
declare -i output_quality=92 # Output image quality (only affects the final
# image and obviously only in lossy formats)
# Colours, see convert -list color to get the list
declare bg_heading=YellowGreen # Background for meta info (size, codec...)
declare bg_sign=SlateGray # Background for signature
declare fg_heading=black # Font colour for meta info box
declare fg_sign=black # Font colour for signature
declare fg_tstamps=white # Font colour for timestamps
# Fonts, see convert -list type to get the list
declare font_tstamps=courier # Used for timestamps behind the thumbnails
declare font_heading=helvetica # Used for meta info box
declare font_sign=$font_heading # Used for the signature box
# Font sizes, in points
declare pts_tstamps=18 # Used for the timestamps
declare pts_meta=16 # Used for the meta info box
declare pts_sign=11 # Used for the signature
# See --shoehorn
declare shoehorned=
# This can only be changed in the configuration file
# Change it to change the safe renanimg:
# When writing the output file, the input name + output extension is
# used (e.g.: "some video.avi.png"), if it already exists, though,
# a number if appended to the name. This variable dictates where the number is
# placed.
# By default "%b-%N.%e" where:
# %b is the basename (file name without extension)
# %N is the appended number
# %e is the extension
# The default creates outputs like "output.avi-1.png"
#
# If overridden with an incorrect value it will be silently set to the default
declare safe_rename_pattern="$DEFAULT_SAFE_REN_PATT"
# Options added always to the ones in the command line
# (command line options override them).
# Note using this is a bit tricky :P mostly because I've no clue of how this
# should be done.
# As an example: you want to set always the title to "My Title" and output
# to jpeg: default_options="-T'My Title' -j"
declare default_options=
 
 
# }}} # End of override-able variables
 
# Options and other internal usage variables, no need to mess with this!
declare -i interval=$DEFAULT_INTERVAL # Interval of captures (=numsecs/numcaps)
declare -i numcaps=$DEFAULT_NUMCAPS # Number of captures (=numsecs/interval)
declare title=""
declare -i fromtime=0 # Starting second (see -f)
declare -i totime=-1 # Ending second (see -t)
declare -a initial_stamps=( ) # Manually added stamps (see -S)
declare -i th_height= # Height of the thumbnails, by default use same as input
declare -i cols=$DEFAULT_COLS # Number of output columns
declare -i manual_mode=0 # if 1, only command line timestamps will be used
declare aspect_ratio=0 # If 0 no transformations done (see -a)
 
declare -a TEMPSTUFF=( ) # Temporal files
 
# Exit codes, same codes as /usr/include/sysexits.h
declare -r EX_OK=0 EX_USAGE=64 EX_UNAVAILABLE=69 \
EX_NOINPUT=66 EX_SOFTWARE=70 EX_CANTCREAT=73 \
EX_INTERRUPTED=79 # This one is not on sysexits.h
 
 
load_config() {
# These are the variables allowed to be overriden in the config file,
# please.
# They're REGEXes, they'll be concatenated to form a regex like
# (override1|override2|...).
# Don't mess with this unless you're pretty sure of what you're doing.
# All this extra complexity is done to avoid including the config
# file directly for security reasons.
declare -ra ALLOWED_OVERRIDES=(
'user'
'user_signature'
'bg_.*'
'font_.*'
'pts_.*'
'fg_.*'
'output_quality'
'DEFAULT_INTERVAL'
'DEFAULT_NUMCAPS'
'DEFAULT_COLS'
'decoder'
'output_format'
'shoehorned'
'timecode_from'
'safe_rename_pattern'
'default_options'
)
 
local compregex=$( sed 's/ /|/g' <<<${ALLOWED_OVERRIDES[*]} )
 
local basecfg="$(basename "$CFGFILE")"
local CONFIGS=( /etc/vcs.conf $CFGFILE ./vcs.conf)
 
for cfgfile in ${CONFIGS[*]} ;do
if [ ! -f "$cfgfile" ]; then continue; fi
 
while read line ; do # auto variable $line
# Don't allow ';', FIXME: dunno how secure that really is
if ! egrep -q '^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*=[^;]*' <<<"$line" ; then
continue
fi
if ! egrep -q "^($compregex)=" <<<"$line" ; then
continue
fi
# FIXME: Only print in verbose mose
# FIXME: Only for really overridden ones
local varname=$(sed -r 's/^[[:space:]]*([a-zA-Z0-9_]*)=.*/\1/'<<<$line)
echo "Overridden variable $varname from file $cfgfile"
eval $line
done <$cfgfile
done
}
 
# {{{ # Convenience functions
 
# Returns true if input is composed only of numbers
is_number() {
egrep -q '^[0-9]+$' <<<"$1"
}
 
# Returns true if input can be parsed as a floating point number
# Accepted: XX.YY XX. .YY (.24=0.24
is_float() {
egrep -q '^([0-9]+\.?([0-9])?+|(\.[0-9]+))$'<<<"$1"
}
 
# Returns true if input is a fraction
# Only accepts XX/YY
is_fraction() {
egrep -q '^[0-9]+/[0-9]+$'<<<"$1"
}
 
# Prints the width correspoding to the input height and the variable
# aspect ratio
# compute_width(height) (=AR*height) (rounded)
compute_width() {
local wfloat=$(bc -lq <<< "$aspect_ratio * $1")
local wint=$(bc -q <<<"($wfloat+0.5)/1")
echo $wint
}
 
# The current code is a tad permissive, it allows e.g. things like
# 10m1h (equivalent to 1h10m)
# 1m1m (equivalent to 2m)
get_interval() {
if is_number "$1" ; then echo $1 ; return 0 ; fi
 
local s=$(tr '[A-Z]' '[a-z]' <<<"$1")
 
# Only allowed characters
if ! grep -q '[0-9smh]' <<<"$s"; then
return $EX_USAGE;
fi
 
# FIXME: Find some cleaner way
local i= c= num= sum=0
for i in $(seq 0 $(( ${#s} - 1)) ); do
c=${s:$i:1}
if is_number $c ; then
num+=$c
else
case $c in
h) num=$(($num * 3600)) ;;
m) num=$(($num * 60)) ;;
s) ;;
*)
return $EX_SOFTWARE
;;
esac
sum=$(($sum + $num))
num=
fi
done
 
# If last element was a number, it's seconds and they weren't added
if is_number $c ; then
sum=$(( $sum + $num ))
fi
 
echo $sum
 
return 0
}
 
pad() {
local len=$1
local str=$2
 
while [ ${#str} -lt $len ]; do
str=0$str
done
 
echo $str
}
 
pretty_stamp() {
if ! is_number "$1" ; then return $EX_USAGE ; fi
 
local t=$1
local h=$(( $t / 3600 ))
t=$(( $t % 3600 ))
local m=$(( $t / 60 ))
t=$(( $t % 60 ))
local s=$t
 
local R=""
 
if [ $h -gt 0 ]; then
R+="$h:"
fi
R+=$(pad 2 "$m"):$(pad 2 $s)
 
echo $R
}
 
get_pretty_size() {
local f="$1"
 
local bytes=$(du -DL --bytes "$f" | cut -f1)
local size=""
 
if [ "$bytes" -gt $(( 1024**3 )) ]; then
local gibs=$(( $bytes / 1024**3 ))
local mibs=$(( ( $bytes % 1024**3 ) / 1024**2 ))
size="${gibs}.${mibs:0:2} GiB"
elif [ "$bytes" -gt $(( 1024**2)) ]; then
local mibs=$(( $bytes / 1024**2 ))
local kibs=$(( ( $bytes % 1024**2 ) / 1024 ))
size="${mibs}.${kibs:0:2} MiB"
elif [ "$bytes" -gt 1024 ]; then
local kibs=$(( $bytes / 1024 ))
bytes=$(( $bytes % 1024 ))
size="${kibs}.${bytes:0:2} KiB"
else
size="${bytes} B"
fi
 
echo $size
}
 
# Rename a file, if the target exists, try with appending numbers to the name
# And print the output name to stderr
safe_rename() {
local from="$1"
local to="$2"
 
# Extension
local ext=$(sed -r 's/.*\.(.*)/\1/g' <<<"$to")
# Basename without extension
local b=$(basename "$2" ".$ext")
 
# safe_rename_pattern is override-able, ensure it has a valid value:
if ! grep -q '%e' <<<"$safe_rename_pattern" ||
! grep -q '%N' <<<"$safe_rename_pattern" ||
! grep -q '%b' <<<"$safe_rename_pattern" ; then
safe_rename_pattern=$DEFAULT_SAFE_REN_PATT
fi
 
local n=1
while [ -f "$to" ]; do # Only executes if $2 exists
to=$(sed "s/%b/$b/g" <<<"$safe_rename_pattern")
to=$(sed "s/%N/$n/g" <<<"$to")
to=$(sed "s/%e/$ext/g" <<<"$to")
 
let 'n++';
done
 
mv "$from" "$to"
echo "$to" >&2
}
 
test_programs() {
for prog in mplayer convert montage ffmpeg bc ; do
type -pf "$prog" >/dev/null
local retval=$?
if [ $retval -ne 0 ] ; then
error "Required program $prog not found!"
return $retval
fi
done
}
 
cleanup() {
if [ -z $TEMPSTUFF ]; then return 0 ; fi
echo "Cleaning up..." >&2 # TODO: Only in verbose mode
rm -rf ${TEMPSTUFF[*]}
TEMPSTUFF=( )
}
 
exithdlr() {
cleanup
}
 
# Print some text to stderr
error() {
echo "$1" >&2
}
 
# }}} # Convenience functions
 
# {{{ # Core functionality
 
MPLAYER_CACHE=
numsecs() {
echo $(grep ID_LENGTH <<<"$MPLAYER_CACHE"| cut -d'=' -f2 | cut -d. -f1)
}
 
compute_timecodes() {
local st=0 numsecs=$(numsecs) end=
end=$numsecs
if [ $st -lt $fromtime ]; then
st=$fromtime
fi
if [ $totime -gt 0 ] && [ $end -gt $totime ]; then
end=$totime
fi
 
local inc=
if [ "$timecode_from" -eq $TC_INTERVAL ]; then
inc=$interval
elif [ "$timecode_from" -eq $TC_NUMCAPS ]; then
# Numcaps mandates: timecodes are obtained dividing the length
# by the number of captures
if [ $numcaps -eq 1 ]; then # Special case, just one capture, center it
inc=$(( ($end-$st) / 2 + 1))
else
inc=$(( ($end-$st) / $numcaps ))
fi
else
error "Internal error"
return $EX_SOFTWARE
fi
 
if [ $inc -gt $numsecs ]; then
error "Interval is longer than video length, skipping $f"
return $EX_USAGE
fi
 
local LTC=( ) stamp=
for stamp in $(seq $st $inc $end); do
LTC+=( $stamp )
done
unset LTC[0] # Initial cap (=$st)
TIMECODES=( ${TIMECODES[*]} ${LTC[*]} )
}
 
process() {
local f=$1
 
local numcols=$cols
 
if [ ! -f "$f" ]; then
error "File \"$f\" doesn't exist"
return $EX_NOINPUT
fi
echo "Processing $f..." >&2
 
# Meta data extraction
# Note to self: Don't change the -vc as it would affect $vdec
MPLAYER_CACHE=$(mplayer -benchmark -ao null -vo null -identify -frames 0 -quiet "$f" 2>/dev/null | grep ^ID)
local vcodec=$(grep ID_VIDEO_FORMAT <<<"$MPLAYER_CACHE" | cut -d'=' -f2) # FourCC
local acodec=$(grep ID_AUDIO_FORMAT <<<"$MPLAYER_CACHE" | cut -d'=' -f2)
local vdec=$(grep ID_VIDEO_CODEC <<<"$MPLAYER_CACHE" | cut -d'=' -f2) # Decoder
local width=$(grep ID_VIDEO_WIDTH <<<"$MPLAYER_CACHE" | cut -d'=' -f2)
local height=$(grep ID_VIDEO_HEIGHT <<<"$MPLAYER_CACHE" | cut -d'=' -f2)
local fps=$(grep ID_VIDEO_FPS <<<"$MPLAYER_CACHE" | cut -d'=' -f2)
# Vidcap/Thumbnail height
local vidcap_height=$th_height
if ! is_number "$vidcap_height" || [ "$vidcap_height" -eq 0 ]; then
vidcap_height=$height
fi
if [ "0" == "$aspect_ratio" ]; then
aspect_ratio=$(bc -lq <<< "$width / $height")
fi
local vidcap_width=$(compute_width $vidcap_height)
 
local numsecs=$(grep ID_LENGTH <<<"$MPLAYER_CACHE"| cut -d'=' -f2 | cut -d. -f1)
if ! is_number $numsecs ; then
error "Internal error!"
return $EX_SOFTWARE
fi
 
local nc=$numcaps
 
# Contact sheet minimum cols:
if [ $nc -lt $numcols ]; then
numcols=$nc
fi
 
# Tempdir
 
local dir=$(mktemp -d -t vcs.XXXXXX)
if [ ! -d "$dir" ]; then
error "Error creating temporary directory"
return $EX_CANTCREAT
fi
TEMPSTUFF+=( "$dir" )
 
local n=
 
# Compute the stamps (if in auto mode)...
TIMECODES=${initial_stamps[*]}
if [ $manual_mode -ne 1 ]; then
compute_timecodes
fi
 
n=1
local p=""
local montage_command="montage -font $font_tstamps -pointsize $pts_tstamps \
-gravity SouthEast -fill white "
local output=$(tempfile --prefix "vcs-" --suffix '-preview.png')
TEMPSTUFF+=( "$output" )
 
# Let's reorder the stamps, this away user-added stamps get their correct
# position also remove duplicates. Note AFAIK sort only sorts lines, that's
# why y replace spaces by newlines.
local stamps=$( sed 's/ /\n/g' <<<"${TIMECODES[*]}" | sort -n | uniq )
 
local VIDCAPFILE=00000001.png
 
# If the temporal vidcap already exists, abort
if [ -f $VIDCAPFILE ]; then
error "Temporal vidcap file ($VIDCAPFILE) exists, remove it before running!."
return $EX_CANTCREAT
fi
 
local NUMSTAMPS=$(wc -w <<<"$stamps")
TEMPSTUFF+=( $VIDCAPFILE )
local capfile=
# TODO: Aspect ratio
for stamp in $stamps; do
# Note that it must be checked against numsecs and not endsec, to allow
# the user manually setting stamps beyond the boundaries
if [ $stamp -gt $numsecs ]; then continue; fi
 
echo "Generating capture #${n}/${NUMSTAMPS}..." >&2
 
p=$(pad 6 $stamp).png
capfile=$dir/$p
 
if [ $decoder -eq $DEC_MPLAYER ]; then
mplayer -sws 9 -ao null -benchmark -vo "png:z=0" -quiet \
-frames 1 -ss $stamp $shoehorned "$f" >/dev/null 2>&1
elif [ $decoder -eq $DEC_FFMPEG ]; then
ffmpeg -y -ss $stamp -i "$f" -an -dframes 1 -vframes 1 -vcodec png \
-f rawvideo $shoehorned $VIDCAPFILE >/dev/null 2>&1
else
error "Internal error!"
return $EX_SOFTWARE
fi || {
local retval=$?
error "The capturing program failed!"
return $retval
}
if [ "0" == "$(du "$VIDCAPFILE" | cut -f1)" ]; then
error "Failed to capture frame (at second $stamp)"
return $EX_SOFTWARE
fi
 
let 'n++' # $n++
 
# Add the timestamp to each vidcap, doing it here is much powerful/simple
# than with the next montage command
# Note the '!', it is necessary to apply aspect ratio change
convert -box '#000000aa' -geometry ${vidcap_width}x${vidcap_height}! \
-fill $fg_tstamps -pointsize $pts_tstamps -gravity SouthEast \
-stroke none -strokewidth 3 -annotate +5+5 " $(pretty_stamp $stamp) " \
$VIDCAPFILE "$capfile"
if [ ! -f "$capfile" ]; then
error "Failed to process capture"
return $EX_CANTCREAT
fi
 
montage_command+=" \"$capfile\""
done
unset capfile
 
# geometry affects the source images, not the target one!
# Note the file name could also be added by using the "-title" option, but I reserved
# it for used set titles
montage_command+=" -geometry ${vidcap_width}x${vidcap_height}+10+5 -tile ${numcols}x -shadow"
if [ "$title" ]; then
montage_command+=" -font $font_heading -fill $fg_heading -title '$title'"
fi
montage_command+=" \"$output\""
 
echo "Composing contact sheet..." >&2
eval $montage_command # eval is required to evaluate correctly the text in quotes!
 
# Codec "prettyfication"
case $( tr '[A-Z]' '[a-z]' <<<$vcodec) in
xvid) vcodec=Xvid ;;
dx50) vcodec="DivX 5" ;;
0x10000001) vcodec="MPEG-1" ;;
0x10000002) vcodec="MPEG-2" ;;
avc1) vcodec="MPEG-4 AVC" ;;
wmv2) vcodec="WMV8" ;; # v2 is same as v8
wmv3) vcodec="WMV9" ;;
esac
if [ "$vdec" == "ffodivx" ]; then
vcodec+=" (MPEG-4)"
elif [ "$vdec" == "ffh264" ]; then
vcodec+=" (h.264)"
fi
 
case $( tr '[A-Z]' '[a-z]' <<<$acodec ) in
85) acodec='MPEG-1 Layer III (MP3)' ;;
80) acodec='MPEG-1 Layer II (MP2)' ;;
mp4a) acodec='MPEG-4 AAC' ;;
353) acodec='WMA2' ;;
354) acodec='WMA3' ;;
"") acodec="no audio" ;;
esac
 
 
local meta="Filename: $(basename "$f")
File size: $(get_pretty_size "$f")
Length: $(pretty_stamp "$numsecs")"
local meta2="Dimensions: ${width}x${height}
Format: $vcodec / $acodec
FPS: $fps"
local signature="$user_signature $user
$PROGRAM_SIGNATURE"
 
# Now let's add meta info
# This one enlarges the image to add the text, and puts
# meta info in two columns
convert -font $font_heading -pointsize $pts_meta \
-background $bg_heading -fill $fg_heading -splice 0x$(( $pts_meta * 4 )) \
-gravity NorthWest -draw "text 10,10 '$meta'" \
-gravity NorthEast -draw "text 10,10 '$meta2'" \
"$output" "$output"
# Finishing touch, signature
 
convert -gravity South -font $font_sign -pointsize $pts_sign \
-background $bg_sign -splice 0x34+0-0 \
-fill $fg_sign -draw "text 10,3 '$signature'" "$output" "$output"
 
if [ $output_format != "png" ]; then
local newout="$(dirname "$output")/$(basename "$output" .png).$output_format"
convert -quality $output_quality "$output" "$newout"
output="$newout"
fi
echo -n "Output wrote to " >&2
safe_rename "$output" "$(basename "$f").$output_format"
 
cleanup
}
 
show_help() {
local P=$(basename $0)
cat <<EOF
Video Contact Sheet *NIX v${VERSION}, (c) 2007 Toni Corvera
 
Usage: $P [options] <file>
 
Options:
-i|--interval <arg> Set the interval to arg. An optional unit can be
used (case-insensitive) , e.g.:
Seconds: 90
Minutes: 3m
Hours: 1h
Use either -i or -n.
-n|--numcaps <arg> Set the number of captured images to arg. Use either
-i or -n.
-f|--from <arg> Set starting time. No caps before this. Same format
as -i.
-t|--to <arg> Set ending time. No caps beyond this. Same format
as -i.
-T|--title <arg> Add a title above the vidcaps.
-u|--user <arg> Set the username found in the signature to this.
-S|--stamp <arg> Add the image found at the timestamp "arg", same format
as -i.
-m|--manual Manual mode: Only timestamps indicated by the user are
used (use in conjunction with -S), when using this
-i and -n are ignored.
-H|--height <arg> Set the output (individual thumbnail) height. Width is
derived accordingly. Note width cannot be manually set.
-a|--aspect <aspect> Aspect ration. Accepts floating point number or fractions.
-j|--jpeg Output in jpeg (by default output is in png).
-h|--help Show this text.
 
Options used for debugging purposes or to tweak the internal workings:
-M|--mplayer Force the usage of mplayer.
-F|--ffmpeg Force the usage of ffmpeg.
--shoehorn <arg> Pass "arg" to mplayer/ffmpeg. You probably don't need it.
 
Examples:
Create a contact sheet with default values (vidcaps at intervals of
$DEFAULT_INTERVAL seconds), the resulting file will be called
input.avi.png:
\$ $P input.avi
 
Create a sheet with vidcaps at intervals of 3 and a half minutes:
\$ $P -i 3m30 input.avi
 
Create a sheet with vidcaps starting at 3 mins and ending at 18 mins,
add an extra vidcap at 2m and another one at 19m:
\$ $P -f 3m -t 18m -S2m -S 19m input.avi
 
EOF
}
 
# }}} # Core functionality
 
#### Execution starts here ####
 
# Execute exithdlr on exit
trap exithdlr EXIT
 
# Test requirements
test_programs || exit $EX_UNAVAILABLE
 
load_config
 
# {{{ # Command line parsing
 
# Based on getopt-parse.bash example.
# On debian systems see </usr/share/doc/util-linux/examples/getopt-parse.bash.gz>
 
# TODO: use no name at all with -u noarg
#eval set -- "${default_options} ${@}"
TEMP=$(getopt -o i:n:u:T:f:t:S:jhFMH:c:ma: \
--long "interval:,numcaps:,username:,title:,from:,to:,stamp:,jpeg,help,shoehorn:,mplayer,ffmpeg,height:,columns:,manual,aspect" \
-n $0 -- "$@")
 
eval set -- "$TEMP"
 
while true ; do
case "$1" in
-i|--interval)
if ! interval=$(get_interval "$2") ; then
error "Interval must be a number (given $2)"
exit $EX_USAGE
fi
if [ "$interval" -le 0 ]; then
error "Interval must be higher than 0, set to the default $DEFAULT_INTERVAL"
interval=$DEFAULT_INTERVAL
fi
timecode_from=$TC_INTERVAL
shift # Option arg
;;
-n|--numcaps)
if ! is_number "$2" ; then
error "Number of caps must be a number! (given $2)"
exit $EX_USAGE
fi
numcaps="$2"
timecode_from=$TC_NUMCAPS
shift # Option arg
;;
-u|--username) user="$2" ; shift ;;
-T|--title) title="$2" ; shift ;;
-f|--from)
if ! fromtime=$(get_interval "$2") ; then
error "Starting timestamp must be a valid interval"
exit $EX_USAGE
fi
shift
;;
-t|--to)
if ! totime=$(get_interval "$2") ; then
error "Ending timestamp must be a valid interval"
exit $EX_USAGE
fi
if [ "$totime" -eq 0 ]; then
error "Ending timestamp was set to 0, set to movie length"
totime=-1
fi
shift
;;
-S|--stamp)
if ! temp=$(get_interval "$2") ; then
error "Timestamps must be a valid interval"
exit $EX_USAGE
fi
initial_stamps=( ${initial_stamps[*]} $temp )
shift
;;
-j|--jpeg) output_format=jpg ;;
-h|--help) show_help ; exit $EX_OK ;;
--shoehorn)
shoehorned="$2"
shift
;;
-F) decoder=$DEC_FFMPEG ;;
-M) decoder=$DEC_MPLAYER ;;
-H|--height)
if ! is_number "$2" ; then
error "Height must be a number (given $2)"
exit $EX_USAGE
fi
th_height="$2"
shift
;;
-a|--aspect)
if ! is_float "$2" && ! is_fraction "$2" ; then
error "Aspect ratio must be expressed as a floating point "\
"number or as a fraction (ie: 1, 1.33, 4/3, 2.5)"
exit 12
fi
aspect_ratio="$2"
shift
;;
-c|--columns)
if ! is_number "$2" ; then
error "Columns must be a number (given $2)"
exit $EX_USAGE
fi
cols="$2"
shift
;;
-m|--manual) manual_mode=1 ;;
--) shift ; break ;;
*) error "Internal error! (remaining opts: $@)" ; exit $EX_SOFTWARE ;
esac
shift
done
 
# Remaining arguments
if [ ! "$1" ]; then
show_help
exit $EX_USAGE
fi
# If -m is used then -S must be used
if [ $manual_mode -eq 1 ] && [ -z $initial_stamps ]; then
error "You must provide timestamps (-S) when using manual mode (-m)"
exit $EX_USAGE
fi
 
set +e # Don't fail automatically
for arg do process "$arg" ; done
 
# }}} # Command line parsing
 
 
# vim:set ts=4 ai: #
Property changes:
Added: svn:executable
/video-contact-sheet/tags/1.0.4b/.
Property changes:
Added: svn:mergeinfo
Merged /video-contact-sheet/branches/1.0a:r262-263
Merged /video-contact-sheet/branches/1.0.1a:r266-267
Merged /video-contact-sheet/tags/0.99a:r261
Merged /video-contact-sheet/branches/1.0.2b:r270-271
Merged /video-contact-sheet/branches/1.0.3b:r276-277
Merged /video-contact-sheet/branches/1.0.4b:r280-281
Merged /video-contact-sheet/tags/1.0.2b:r274