Subversion Repositories pub

Compare Revisions

Ignore whitespace Rev 267 → Rev 268

/video-contact-sheet/trunk/vcs
1,11 → 1,21
#!/bin/bash
 
# $Rev: 246 $ $Date: 2007-04-11 00:06:25 +0200 (dc, 11 abr 2007) $
# $Rev: 249 $ $Date: 2007-04-13 05:29:36 +0200 (dv, 13 abr 2007) $
 
declare -r VERSION="1.0.1a"
#
# History:
#
# 1.0a:
# 1.0.1a:
# * 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
24,57 → 34,124
# 0.5a: * First usable version
# 0.1: * First proof of concept
 
declare -r VERSION="0.99.1a"
set -e
 
# Options
declare -i interval=300 # Interval of captures (= numsecs / numcaps)
declare -i numcaps=16 # Number of captures (= numsecs / interval)
# 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_META=gray # Make the heading gray
#
# The variables that can be overriden are below the block of constants ahead.
declare -r CFGFILE=~/.vcs.conf
 
declare user=$(id -un)
declare -r USER_SIGNATURE="Preview created by"
declare -r PROGRAM_SIGNATURE="with Video Contact Sheet *NIX ${VERSION} <http://p.outlyer.net/vcs/>"
# Constants {{{
# see $METHOD
declare -ri METHOD_MPLAYER=1 METHOD_FFMPEG=2
# See $derive_from
declare -ri INTERVAL=1 NUMCAPS=3
# These can't be overriden, modify this line if you feel the need
declare -r PROGRAM_SIGNATURE=<<EOT
with Video Contact Sheet *NIX ${VERSION} <http://p.outlyer.net/vcs/>
EOT
 
# Options used in imagemagick, these options set the final aspect
# of the contact sheet so tweak them to your liking
#
declare -i OUTPUT_QUALITY=92 # Output image quality (only affects the final image,
# and only in lossy formats)
# Colours, see convert -list color
declare -r BG_META=YellowGreen # Background for meta info (size, codec...)
declare -r BG_SIGN=SandyBrown # Background for signature
declare -r FG_META=black # Font colour for meta info box
declare -r FG_SIGN=black # Font colour for signature
declare -r FG_STAMPS=white # Font colour for timestamps
# Fonts, see convert -list type
declare -r FONT_STAMPS=courier # Used for timestamps behind the thumbnails
declare -r FONT_META=helvetica # Used for meta info box
declare -r FONT_SIGN=$FONT_META # Used for the signature box
# Font sizes, in points
declare -i PS_STAMPS=18 # Used for the timestamps
declare -i PS_META=16 # Used for the meta info box
declare -i PS_SIGN=11 # Used for the signature
# }}} # End of constants
 
# Constants and other internal usage variables, no need to mess with this!
# Override-able variables {{{
 
declare -i DEFAULT_INTERVAL=300
declare -i DEFAULT_NUMCAPS=16
# 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 -ri INTERVAL=1 NUMCAPS=3
declare -i derive_from=$INTERVAL
declare -ri DEFAULT_INTERVAL=$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 -ri METHOD_MPLAYER=1
declare -ri METHOD_FFMPEG=2
declare -i METHOD=$METHOD_FFMPEG
# Options used in imagemagick, these options set the final aspect
# of the contact sheet
declare OUTFMT=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_META=YellowGreen # Background for meta info (size, codec...)
declare BG_SIGN=SandyBrown # Background for signature
declare FG_META=black # Font colour for meta info box
declare FG_SIGN=black # Font colour for signature
declare FG_STAMPS=white # Font colour for timestamps
# Fonts, see convert -list type to get the list
declare FONT_STAMPS=courier # Used for timestamps behind the thumbnails
declare FONT_META=helvetica # Used for meta info box
declare FONT_SIGN=$FONT_META # Used for the signature box
# Font sizes, in points
declare PS_STAMPS=18 # Used for the timestamps
declare PS_META=16 # Used for the meta info box
declare PS_SIGN=11 # Used for the signature
# See --shoehorn
declare shoehorned=
 
# Internal variables:
# }}} # 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 initial_stamps=( ) # Stamps added to the calculated ones (see -S)
declare OUTFMT=png
declare shoehorned= # See --shoehorn
declare -a initial_stamps=( ) # Stamps added to the calculated ones (see -S)
declare -i th_height= # Height of the thumbnails, by default use same as input
declare -i cols=2 # Number of output columns
declare -i manual_mode=0 # if 1, only command line timestamps will be used
 
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_.*'
'PS_.*'
'FG_.*'
'OUTPUT_QUALITY'
'DEFAULT_INTERVAL'
'DEFAULT_NUMCAPS'
'METHOD'
'OUTFMT'
'shoehorned'
'derive_from'
)
 
if [ ! -f "$CFGFILE" ]; then return 0 ; fi
 
local compregex=$( sed 's/ /|/g' <<<${ALLOWED_OVERRIDES[*]} )
 
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
echo "Overridden variable" $(sed -r 's/^[[:space:]]*([a-zA-Z0-9_]*)=.*/\1/'<<<$line)
eval $line
done <$CFGFILE
}
 
# {{{ # Convenience functions
 
is_number() {
82,25 → 159,47
return $?
}
 
# 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")
local len_n=$(( ${#s} - 1 )) # Length of the theoretical numeric part
local u=${s:$len_n}
local n=${s:0:$len_n}
local i=0
 
if ! is_number "$n" ; then return 1 ; fi
# Only allowed characters
if ! grep -q '[0-9smh]' <<<"$s"; then
return 1;
fi
 
case "$u" in
s) i=$n ;;
m) i=$((n * 60)) ;;
h) i=$((n * 3600)) ;;
*) return 2 ; break ;;
esac
# 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 2
;;
esac
sum=$(($sum + $num))
num=
fi
done
 
echo $i
# 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() {
173,6 → 272,7
done
 
mv "$from" "$to"
echo "$to" >&2
}
 
test_programs() {
293,18 → 393,26
return 17
fi
 
# Get the stamps...
local n=
 
local n=$(( $startsec + $in ))
local stamps=( ${initial_stamps[*]} $n )
# Get the stamps (if in auto mode)...
 
while [ $n -le $endsec ]; do
n=$(( $n + $in ))
if [ $n -gt $endsec ]; then break; fi
local stamps=( )
if [ $manual_mode -ne 1 ]; then
 
stamps=( ${stamps[*]} $n )
done
n=$(( $startsec + $in ))
stamps=( ${initial_stamps[*]} $n )
 
while [ $n -le $endsec ]; do
n=$(( $n + $in ))
if [ $n -gt $endsec ]; then break; fi
 
stamps=( ${stamps[*]} $n )
done
else
stamps=( ${initial_stamps[*]} )
fi
 
n=1
local p=""
local cap=""
312,12 → 420,13
-gravity SouthEast -fill white "
local output=$(tempfile --prefix "vcs-" --suffix '-preview.png' -d .)
 
# Let's reorder the stamps, this away user-added stamps get their correct position
local temp=""
for stamp in ${stamps[*]} ; do
temp+="$stamp\n"
done
stamps=$(echo -e $temp | sort -n)
# 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.
#
# Note that stamps keeps being an array and stamps[1..N] still hold their
# old values, although it's treated as a string after this
stamps=$( sed 's/ /\n/g' <<<"${stamps[*]}" | sort -n | uniq )
 
local VIDCAPFILE=00000001.png
 
327,6 → 436,7
exit 134
fi
 
local NUMSTAMPS=$(wc -w <<<"$stamps")
# TODO: Aspect ratio
for stamp in $stamps; do
# Note that it must be checked against numsecs and not endsec, to allow
333,7 → 443,7
# the user manually setting stamps beyond the boundaries
if [ $stamp -gt $numsecs ]; then continue; fi
 
echo "Generating capture #${n}/${#stamps[*]}..." >&2
echo "Generating capture #${n}/${NUMSTAMPS}..." >&2
 
if [ $METHOD -eq $METHOD_MPLAYER ]; then
mplayer -sws 9 -ao null -benchmark -vo "png:z=0" -quiet \
344,7 → 454,10
else
error "Internal error!"
return 142
fi
fi || {
error "The capturing program failed!"
return 143
}
 
p=$(pad 6 $stamp).png
# mv 00000001.png $dir/$p
382,6 → 495,7
0x10000001) vcodec="MPEG-1" ;;
0x10000002) vcodec="MPEG-2" ;;
avc1) vcodec="MPEG-4 AVC" ;;
wmv2) vcodec="WMV 8" ;; # WMV2 is v8
esac
if [ "$vdec" == "ffodivx" ]; then
vcodec+=" (MPEG-4)"
393,6 → 507,7
85) acodec='MPEG-1 Layer III (MP3)' ;;
80) acodec='MPEG-1 Layer II (MP2)' ;;
mp4a) acodec='MPEG-4 AAC' ;;
353) acodec='WMA 2' ;;
"") acodec="no audio" ;;
esac
 
428,6 → 543,7
output="$newout"
fi
echo -n "Output wrote to " >&2
safe_rename "$output" "$(basename "$f").$OUTFMT"
}
 
455,6 → 571,9
-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.
-j|--jpeg Output in jpeg (by default output is in png).
489,6 → 608,8
# Test requirements
test_programs || exit 54
 
load_config
 
# {{{ # Command line parsing
 
# Based on getopt-parse.bash example.
495,8 → 616,8
# On debian systems see </usr/share/doc/util-linux/examples/getopt-parse.bash.gz>
 
# FIXME: use username / no name at all with -u noarg, and not -u
TEMP=$(getopt -o i:n:u:T:f:t:S:jhFMH:c: \
--long "interval:,numcaps:,username:,title:,from:,to:,stamp:,jpeg,help,shoehorn:,mplayer,ffmpeg,height:,columns:" \
TEMP=$(getopt -o i:n:u:T:f:t:S:jhFMH:c:m \
--long "interval:,numcaps:,username:,title:,from:,to:,stamp:,jpeg,help,shoehorn:,mplayer,ffmpeg,height:,columns:,manual" \
-n $0 -- "$@")
 
eval set -- "$TEMP"
576,6 → 697,7
cols="$2"
shift
;;
-m|--manual) manual_mode=1 ;;
--) shift ; break ;;
*) error "Internal error! (remaining opts: $@)" ; exit 76 ;
esac
587,6 → 709,12
show_help
exit 67
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 68
fi
 
for arg do process "$arg" ; done
 
# }}} # Command line parsing