#!/bin/bash # postprocess images from camera # - rotate portrait images # - rename by date/time [/title] # - note: jhead will only rename images with filenames which are # "mostly numerical" (jhead(1)) # - look for audio annotations and rename alongside image # - rename and recode movies to a more reasonable size # # dependancies: # bash # perl # jhead # jpegtran # lame (for audio annotations) # mplayer/mencoder (for movies) # # Ben Low ben@bdlow.net Apr03 # # enable *() and friends shopt -s extglob usage() { echo "usage: $0 [title] " echo " or $0 [title]" exit 1 } # usage: if first or last argument isn't a filename, assume title if [ $# -eq 0 ]; then usage; fi if [ $# -gt 1 ]; then # - use an array to get at last arg (any other way?) args=("$@") n=${args[${#args[@]}-1]} #echo "$1 $n" if ! [ -e "$1" ]; then title=$1 shift elif ! [ -e "$n" ]; then title=$n # leave on arg list (can't pop $@) fi echo "title = [$title]" fi #strftime='%c' strftime='%b %d %a %X %Y'${title:+ - $title} set -e trap 'echo "$0 FAILED!"' ERR tmpdir=`mktemp -d -t cam.XXXXXXX` trap 'echo "$0 FAILED! (see $tmpdir ?)"' ERR for f in "$@" do # avoid error on "title" (e.g. if last arg) if ! [ -e "$f" ]; then if [ "$f" != "$title" ]; then echo "$f: file not found"; fi continue fi case "$f" in *.JPG|*.jpg|*.JPEG|*.jpeg) # need to rotate? r=`jhead "$f" | perl -wne '$_ =~ /^Orientation\s*:\s*rotate\s*(\d+)$/ && print $1'` cmd='' if [ "$r" ]; then cmd="jpegtran -rotate $r -outfile &o &i" fi # -ft = file mod time == exif time # -n'%...' = rename file using strftime format, using exif time echo "$f${r:+ rotating $r}" if ! jhead -ft -nf"${strftime}" ${cmd:+-cmd "$cmd"} "$f"; then echo "jhead failed, aborting" break fi # look for audio (associated annotation) # - note: jhead's -ft option will have set the image file mod time # to the exif time, so can use this to stamp the audio file # - gotta love shell quoting w="`perl -MPOSIX -we '$f=shift; { $_ = $f; if (s/IMG(.*)\.JPE?G$/SND$1.WAV/ && -e $_) {$f = $_; last} $_ = $f; if (s/img(.*)\.jpe?g$/snd$1.wav/ && -e $_) {$f = $_; last} $_ = $f; if (s/\.jpe?g$/.wav/ && -e $_) {$f = $_; last} $_ = $f; if (s/\.JPE?G$/.WAV/ && -e $_) {$f = $_; last} #warn "audio file not found for [$f]\n"; exit; } $nf = \"'"$strftime"'\"; rename $f, strftime "$nf.wav", localtime((stat($f))[9]); print "$nf"' "$f"`" # vorbis isn't "tuned" for 11.025kHz, resampling to ~44k (filesize *= 2) [ "$w" ] && lame "$w" "`basename "$w" .wav`.mp3" ;; *.AVI|*.avi) # movie audio parameters CHANNELS=1 SRATE=11025 # target coding rates: VRATE=496 ARATE=16 nf='' nf="`perl -MPOSIX -we '$f=shift; print strftime \"'"$strftime"'\", localtime((stat($f))[9])' "$f"`" # mplayer's -info uses : to delimit fields info="comment=\"`echo $nf | sed 's/:/;/g'`\"" echo "encoding $f -> $nf.avi at $(($VRATE + $ARATE)) kb/s" of="$nf"-$(($VRATE+$ARATE))k.avi rm -f divx2pass.log 2>/dev/null for p in 1 2; do mencoder "$f" -include "$f".conf -channels $CHANNELS -srate $SRATE \ -oac mp3lame -lameopts mode=3:abr:br=$ARATE \ -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=$VRATE:vpass=$p \ -info "$info" -o "$of" >"$tmpdir"/mencoder.out 2>&1 done touch -r "$f" "$of" VRATE=$(($VRATE / 4)) echo "encoding $f -> $nf.avi at $(($VRATE + $ARATE)) kb/s" of="$nf"-$(($VRATE+$ARATE))k.avi rm -f divx2pass.log 2>/dev/null for p in 1 2; do mencoder "$f" -include "$f".conf -channels $CHANNELS -srate $SRATE \ -oac mp3lame -lameopts mode=3:abr:br=$ARATE \ -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=$VRATE:vpass=$p \ -info "$info" -o "$of" >"$tmpdir"/mencoder.out 2>&1 done touch -r "$f" "$of" rm -f divx2pass.log 2>/dev/null # generate a thumbnail (filename 00000001.jpg) of="$nf".jpg mplayer "$f" -include "$f".conf -ao null -frames 1 \ -vo jpeg -jpeg outdir="$tmpdir" >"$tmpdir"/mplayer.out 2>&1 && cp "$tmpdir"/+(0)1.jpg "$of" touch -r "$f" "$of" # rename original, but don't overwrite anything if ! [ -e "$nf".avi ]; then mv "$f" "$nf".avi # move config as well [ -e "$f".conf ] && mv "$f".conf "$nf".avi.conf fi ;; *) echo "$f: unhandled file type" ;; esac done rm -f "$tmpdir/*" && rmdir "$tmpdir"