#!/bin/sh # Copyright (C) 2007 by Stefan Talpalaru # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or # (at your option) version 3 as published by the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # create the following symlinks: any2ogg.sh and any2wav.sh # required software (if missing, the generic converters will be used): # input formats: # .ape ---> 'mac' from http://sourceforge.net/projects/mac-port/ # .aac ---> faad2 # .flac ---> flac # .mpc ---> musepack-tools # .mp3 ---> mpg123, id3lib # .ogg ---> vorbis-tools # .wv ---> wavpack # generic converters: mplayer, ffmpeg or vlc # output formats: # mp3 ---> lame # ogg ---> vorbis-tools # TODO: # - better output directory scheme T=/tmp/any2mp3$$ trap "rm -f $T; exit" 0 1 2 5 15 WF='' # work file. the one converted by 'lame' KEEP=0 # keep orig file LAME_OPTS='' # extra options OGGENC_OPTS='' # extra options DEFAULT_MP3="" DEFAULT_OGG="" DEFAULT_WAV="" OUTPUT_DIR="" case $0 in *mp3*) OUTPUT=mp3 QUAL=6 #quality ENCODER="lame" ENCODER_BETTER="lower" DEFAULT_MP3="(default)" ;; *ogg*) OUTPUT=ogg QUAL=3 #quality ENCODER="oggenc" ENCODER_BETTER="higher" DEFAULT_OGG="(default)" ;; *wav*) OUTPUT=wav QUAL=6 #quality ENCODER="lame" ENCODER_BETTER="lower" DEFAULT_WAV="(default)" ;; esac USAGE="usage: `basename $0` [options] file|dir...\n\ supported input formats: wav, mp3, ogg, aac (mp4, m4a), ape, flac, mpc, wv\n\ options:\n\ -h | --help\t\tthis help\n\ -q | --quality QUAL\tencoding quality as understood by '$ENCODER' - $ENCODER_BETTER is better (default: $QUAL)\n\ -k | --keep\t\tkeep original file (unless it's a *.$OUTPUT)\n\ -d | --dir DIR\t\tput the result in DIR (create if missing)\n\ --wav\t\t\toutput wav $DEFAULT_WAV\n\ --mp3\t\t\toutput mp3 $DEFAULT_MP3\n\ --ogg\t\t\toutput ogg/vorbis $DEFAULT_OGG" # get opts OPTS=`getopt -s sh -o "hq:kd:" -l "help,quality:,keep,ogg,mp3,wav,dir:" -- "$@"` [ $? != 0 ] && { echo -e "$USAGE"; exit 1; } eval set -- "$OPTS" while :; do case "$1" in -h|--help) echo -e "$USAGE" exit 1 ;; -q|--quality) QUAL="$2" shift 2 ;; -k|--keep) KEEP=1 shift ;; -d|--dir) OUTPUT_DIR="$2" shift 2 ;; --ogg) OUTPUT="ogg" shift ;; --mp3) OUTPUT="mp3" shift ;; --wav) OUTPUT="wav" shift ;; --) shift break ;; *) echo "parsing error!" exit 1 ;; esac done [ $# = 0 ] && { echo -e "$USAGE"; exit 1; } #recursive function reenc () { for F; do # cosmetic change F=${F%/} # descend in directories [ -d "$F" ] && { reenc "$F"/*; continue; } # skip '*' returned in empty directories [ ! -e "$F" ] && continue # decoding WF=`echo $F | sed 's/\.[a-zA-Z0-9]*$//'`.wav CONVERTED=0 case "$F" in *.wav|*.WAV) # no decoding needed WF="$F" CONVERTED=1 ;; *.mp3|*.MP3) case $OUTPUT in mp3) # no decoding needed WF="$F" CONVERTED=1 ;; *) # decode to wav echo "\"$F\" -> \"$WF\"" which mpg123 &>/dev/null && mpg123 -w "$WF" "$F" &>/dev/null && CONVERTED=1 # get metadata which id3info &>/dev/null && \ { ID_TITLE=`id3info "$F" | grep "^=== TIT2" | sed 's/^.*):\ //'` ID_ARTIST=`id3info "$F" | grep "^=== TPE1" | sed 's/^.*):\ //'` ID_ALBUM=`id3info "$F" | grep "^=== TALB" | sed 's/^.*):\ //'` ID_YEAR=`id3info "$F" | grep "^=== TYER" | sed 's/^.*):\ //'` ID_TRACK=`id3info "$F" | grep "^=== TRCK" | sed 's/^.*):\ //'` LAME_OPTS="--tt \"$ID_TITLE\" --ta \"$ID_ARTIST\" --tl \"$ID_ALBUM\" --ty \"$ID_YEAR\" --tn \"$ID_TRACK\"" OGGENC_OPTS="-t \"$ID_TITLE\" -a \"$ID_ARTIST\" -l \"$ID_ALBUM\" -N \"$ID_TRACK\"" } ;; esac ;; *.ogg|.OGG) # decode to wav echo "\"$F\" -> \"$WF\"" which oggdec &>/dev/null && oggdec -o "$WF" "$F" &>/dev/null && CONVERTED=1 # get metadata which ogginfo &>/dev/null && \ { ID_TITLE=`ogginfo "$F" | tr '\t' ' ' | grep -i '^ TITLE=' | cut -d '=' -f 2` ID_ARTIST=`ogginfo "$F" | tr '\t' ' ' | grep -i '^ ARTIST=' | cut -d '=' -f 2` ID_ALBUM=`ogginfo "$F" | tr '\t' ' ' | grep -i '^ ALBUM=' | cut -d '=' -f 2` ID_TRACK=`ogginfo "$F" | tr '\t' ' ' | grep -i '^ TRACKNUMBER=' | cut -d '=' -f 2` LAME_OPTS="--tt \"$ID_TITLE\" --ta \"$ID_ARTIST\" --tl \"$ID_ALBUM\" --tn \"$ID_TRACK\"" OGGENC_OPTS="-t \"$ID_TITLE\" -a \"$ID_ARTIST\" -l \"$ID_ALBUM\" -N \"$ID_TRACK\"" } ;; *.aac|*.AAC|*.mp4|*.MP4|*.m4a|*M4A) # decode to wav echo "\"$F\" -> \"$WF\"" which faad &>/dev/null && faad -d -o "$WF" "$F" &>/dev/null && CONVERTED=1 && \ { # get metadata ID_TITLE=`faad -i "$F" 2>&1 | grep "^title:" | sed 's/^title: //'` ID_ARTIST=`faad -i "$F" 2>&1 | grep "^artist:" | sed 's/^artist: //'` ID_ALBUM=`faad -i "$F" 2>&1 | grep "^album:" | sed 's/^album: //'` ID_YEAR=`faad -i "$F" 2>&1 | grep "^date:" | sed 's/^date: //'` ID_TRACK=`faad -i "$F" 2>&1 | grep "^track:" | sed 's/^track: //'` LAME_OPTS="--tt \"$ID_TITLE\" --ta \"$ID_ARTIST\" --tl \"$ID_ALBUM\" --ty \"$ID_YEAR\" --tn \"$ID_TRACK\"" OGGENC_OPTS="-t \"$ID_TITLE\" -a \"$ID_ARTIST\" -l \"$ID_ALBUM\" -N \"$ID_TRACK\"" } ;; *.ape|*.APE) echo "\"$F\" -> \"$WF\"" which mac &>/dev/null && mac "$F" "$WF" -d &>/dev/null && CONVERTED=1 ;; *.flac|*.FLAC) echo "\"$F\" -> \"$WF\"" which flac &>/dev/null && flac -d "$F" &>/dev/null && CONVERTED=1 ;; *.mpc|*.MPC) echo "\"$F\" -> \"$WF\"" which mppdec &>/dev/null && mppdec "$F" "$WF" &>/dev/null && CONVERTED=1 ;; *.wv|*.WV) echo "\"$F\" -> \"$WF\"" which wvunpack &>/dev/null && wvunpack "$F" -o "$WF" &>/dev/null && CONVERTED=1 ;; *.txt|*.TXT|*.doc|*.DOC|*.cue|*.CUE|*.log|*.LOG|*.url|*.URL|*.htt|*.ini|*.m3u|*.M3U|*.pls|*.PLS|*.sfv|*.SFV|*.torrent|*.nfo|*.NFO|*.jpg|*.JPG|*.gif|*.GIF|*.png|*.PNG|*.bmp|*.BMP) #skip files known not to be audio (speeds up processing) CONVERTED=1 ;; *) # unknown format WF="any2mp3$$.wav" echo "\"$F\" -> \"$WF\"" #try generic converters if [ $CONVERTED = 0 ] && which mplayer &>/dev/null; then echo -n "using mplayer... " mplayer -quiet -vc null -vo null -ao pcm:fast:file="$WF" "$F" &>/dev/null && \ CONVERTED=1 || { echo "failed"; rm -f "$WF"; } echo fi if [ $CONVERTED = 0 ] && which ffmpeg &>/dev/null; then echo -n "using ffmpeg... " ffmpeg -y -vn -i "$F" "$WF" &>/dev/null && \ CONVERTED=1 || { echo "failed"; rm -f "$WF"; } echo fi if [ $CONVERTED = 0 ] && which vlc &>/dev/null; then echo -n "using vlc... " vlc --quiet -I rc --novideo --sout="#transcode{acodec=s16l}:duplicate{dst=std{access=file,mux=wav,dst='$WF'}}" "$F" vlc:quit &>/dev/null && \ CONVERTED=1 || { echo "failed"; rm -f "$WF"; } echo fi ;; esac # encoding [ $CONVERTED = 0 -o ! -e "$WF" ] && echo "failed to decode \"$F\"" && continue case $OUTPUT in mp3) eval nice -10 lame --vbr-new --nohist -V $QUAL "$LAME_OPTS" \"$WF\" \"$T\" LAME_OPTS='' ;; ogg) eval nice -10 oggenc "$OGGENC_OPTS" -q $QUAL -o \"$T\" \"$WF\" OGGENC_OPTS='' ;; esac # metadata case "$F" in *mp3|*MP3) [ $OUTPUT = "mp3" ] && id3cp "$F" "$T" >/dev/null ;; esac # final move [ $OUTPUT != "wav" ] && mv "$T" "`echo $F | sed 's/\.[a-zA-Z0-9]*$//'`.$OUTPUT" # cleanup case "$F" in *$OUTPUT) # already overwritten : ;; *) # delete it [ $KEEP = 0 ] && rm -f "$F" ;; esac # delete $WF if different than $F [ $OUTPUT != "wav" -a "$WF" != "$F" ] && rm -f "$WF" done } #reenc "$@" if [ -z "$OUTPUT_DIR" ]; then reenc "$@" else KEEP=0 mkdir -p "$OUTPUT_DIR" cp -a "$@" "$OUTPUT_DIR"/ reenc "$OUTPUT_DIR" fi