#!/bin/bash # # flactool -- Convert FLAC to MP3 files # # VENUE # # Motivation: export lossless audio files from your multimedia archive for # portable audio devices which cannot play FLAC. # # DESCRIPTION # # Decompresses FLAC to WAV and then encodes WAV as MP3. The original FLAC files # stay untouched, and all files not matching "*.flac" are ignored. Conversion # can happen in multiple parallel jobs (default: 2). # # To convert WAV to MP3 this schript utilizes LAME with "-V 0 -q 1 --vbr-new" # which results in a variable bitrate of ~245 kbps. The file-size is reduced # about 70%. These options are equivalent to "--preset fast extreme". These # settings will normally produce "transparent" encoding. It means that most # people can't distinguish the MP3 from the original FLAC in an ABX blind test. # For more information see http://wiki.hydrogenaudio.org/index.php?title=LAME # and http://wiki.hydrogenaudio.org/index.php?title=Flac # # CONVERSION MODES # # Inplace (default): Move FLAC to MP3 in the same directory. # # Copy: Create MP3 in a separate directory. # # REQUIREMENTS # # bash, flac, metaflac, lame, id3 # # INSTALL # # $ chmod a+x flactool # $ cp flactool /usr/local/bin # $ cp flactool ~/bin # alternate location # ######################### # $Compile: ./flactool -o 'e:/MUSIC' '/cygdrive/h/av/album/6 Rock & Pop/Yello/Yello (1994) Zebra'$ # $Compile: ./flactool -n -o 'e:/MUSIC' '/cygdrive/h/av/album/6 Rock & Pop/Yello/Yello (1994) Zebra'$ # $Compile: find '/cygdrive/h/av/album/6 Rock & Pop/Yello/Yello (1994) Zebra' -iname '*.flac'$ script=`basename "$0"` version='1.0.1' ######################################################################## # Portability / Environment / Options E_MISSING=64 # missing programs E_BADARGS=65 # bad argument format E_BADDIR=66 # can't change directory case "`uname`" in CYGWIN*) under_cygwin=1 CYGWIN=${CYGWIN:-tty notitle glob nontsec} CYGWIN+=" winsymlinks";; *) under_cygwin=0;; esac function Panic { cat <&2 Panic! in shell $$, pipe $?, terminal `tty`: $* $script exits with -1 EOF exit -1 } function Ok { [ -z "$*" ] || echo "$*"; exit 0 } function CroakArgs { Usage; exit $E_BADARGS } function CroakUnlessGnuFind { if ((!$have_gnu_find)); then echo "CAUTION: GNU find required" >&2 exit $E_NOTGNU fi } function Version { cat <&2 $script version $version EOF } function Usage { Version; cat <&2 Usage: $script [-o OUTDIR] [-n] [-r] [DIRNAME | FLACFILE] $script [-h | -V] EOF } function Help { Usage; cat <&2 Description: Convert FLAC to high-quality MP3 files. When no input directory or file name is specified converts all .flac-files in current directory. This portable shell script should work on any UNIX and Windows (Cygwin) system. Simply copy it into your path (e.g. to "/usr/local/bin" or "~/bin"). Maintained at . Options: -p, -p N Start N parallel conversion jobs (default: $optmaxprocs). -o DIR Output directory for MP3 files. Default is to write each MP3 along with its source FLAC. -r Find FLAC recursively. -V Print version information. -h, -H Print this information. Prerequisites: bash, flac, metaflac, lame, id3 Exit codes: 0 Indicates success to the shell. -1 Indicates an unexpected error. $E_MISSING Missing programs $E_BADARGS Bad command-line arguments. $E_BADDIR Invalid directory. EOF } optrecurse=0 optmaxprocs=2 optdry=0 optin= optout= optmetacmd=id3 while getopts 'nro:P:hHV' opt; do case $opt in P) optmaxprocs=$OPTARG;; r) optrecurse=1;; n) optdry=1;; o) optout="$OPTARG";; P) optmaxprocs=$OPTARG;; V) Version; Ok;; [hH]) Help; Ok;; *) CroakArgs;; esac done shift $(($OPTIND - 1)) optin=${1:-.} if [ -d "$optin" ]; then [ -z "$2" ] || { echo "Only one search directory allowed" >&2 exit $E_BADDIR } elif [ -f "$optin" ]; then ((!$optrecurse)) || CroakArgs else echo "$optin: directory not found" >&2 exit $E_BADDIR fi # A few Windows tools, such as find.exe, link.exe and sort.exe, may conflict # with the Cygwin versions. Try the full path /usr/bin/find then. find=`which find` if ((!$under_cygwin)); then res=`$find --version` if [ "$?" -ne "0" ]; then cat <&2 CAUTION: Find is '$find', the Microsoft 'find' utility. Possibly the Cygwin-bin-directory does not come first in PATH (see "~/.bash_login" and "/etc/profile"). EOF find=/usr/bin/find res=`$find --version` if [ "$?" -ne "0" ]; then Panic "'$find' not found" else cat <&2 WARNING: Using '$find' explicitly. EOF fi fi fi res=`$find -regextype posix-egrep 2>&1 &>/dev/null` if [ "$?" -ne "0" ]; then # some prehistoric find version cat <&2; WARNING: '$find' does not understand '-regextype'. EOF have_gnu_find=0 else have_gnu_find=1 fi ######################################################################## # Main if [[ -d "$optin" ]] then # Find flac, lame, id3, metaflac. for prog in flac lame id3 metaflac do which "$prog" >/dev/null || { echo "'$prog' program not found" >&2 exit $E_MISSING } done # Find all FLAC files and fork this script on each through xargs. Parallize # encoding. declare -a findopts (($optrecurse)) || findopts=(-maxdepth 1) ouropts=() i=0 [ -n "$optout" ] && { ouropts[$((i++))]="-o" ouropts[$((i++))]="$optout" } (($optdry)) && ouropts[$((i++))]="-n" $find "$optin" "${findopts[@]}" -iname '*.flac' -print0 | { xargs -0 -P $optmaxprocs -I{} "$0" "${ouropts[@]}" "{}" } else declare base="${optin%%.flac}" declare flacfile="${optin}" mp3file="${base}.mp3" declare -a lameopts=(-V 0 --vbr-new -q 1 -m j) declare -a flacopts=(--silent) [ -n "${optout}" ] && mp3file="${optout}/$(basename "${mp3file}")" cat < WAV -> MP3 # https://wiki.archlinux.org/index.php/Convert_Flac_to_Mp3 (($optdry)) || { flac -d -c "${flacopts[@]}" "$flacfile" | lame "${lameopts[@]}" - "$mp3file" } # "lame" does not copy the existing ID3 tags to the new file. Therefore we # an utility such as "id3" or "exiftool". case "$optmetacmd" in id3) # Default genre #12 is "Other". See # for tag in ARTIST TITLE ALBUM GENRE TRACKNUMBER DATE COMMENT do x="$(metaflac "$flacfile" --show-tag=$tag | sed s/.*=//g)" eval $tag=\"$x\" done cat <