]> Freerunner's - dotfiles.git/commitdiff
scripts: add flac2mp3.sh
authorAndre Ramnitz <tux.rising@gmail.com>
Sun, 24 Nov 2024 22:57:23 +0000 (23:57 +0100)
committerAndre Ramnitz <tux.rising@gmail.com>
Sun, 24 Nov 2024 22:57:23 +0000 (23:57 +0100)
dot-local/bin/flac2mp3.sh [new file with mode: 0755]

diff --git a/dot-local/bin/flac2mp3.sh b/dot-local/bin/flac2mp3.sh
new file mode 100755 (executable)
index 0000000..0c775c0
--- /dev/null
@@ -0,0 +1,389 @@
+#! /bin/bash
+#
+# This script converts a directory containing .flac files to MP3 using lame encoder
+#
+# Basic logic for FLAC --> ID3v1, v2 conversion
+# If ALBUMARTIST defined then ALBUMARTIST --> (-, TPE2)
+#   else if BAND defined then BAND --> (-, TPE2)
+#     else ARTIST --> (-, TPE2)
+# ALBUM --> (ALBUM, TALB)
+# ARTIST --> (ARTIST, TPE1)
+# TRACKNUMBER --> (TRACK, TRCK)
+# TITLE --> (TITLE, TIT2)
+# GENRE --> (GENRE, TCON)
+# COMMENT --> (COMMENT, COMM)
+# If DATE defined then DATE --> (YEAR, TYER)
+#   else if YEAR defined then YEAR --> (YEAR, TYER)
+# If DISCNUMBER defined then DISCNUMBER --> (-, TPOS)
+#   else TPOS=1
+# If coverfile defined, add that to MP3 as well (ID3v2 only, APIC):
+#   search order for cover images: TPE2 - TALB.*, TALB.*, cover.* Cover.* 
+#                                  folder.* Folder.* front.* Front.*
+#                                  where extension can be jpg, png or gif
+# Version history
+# 1.0 first version
+# 2.0 extended with command line options
+# 2.1 in case of error in processing, dumps the content of lame command line
+#     to help debug
+#     uses mktemp instead of using fixed file names 
+#     (can run multiple instances of script)
+# 3.0 full directory walk added, so entire trees can be converted (if not existing already)
+#
+
+#set -xv
+
+VERSION="3.0"
+
+print_usage ()
+{
+   echo "Usage: `basename $0` [options] <src-path>"
+   echo "Options: -h   Print usage"
+   echo "         -d   Debug level (0..2)"
+   echo "         -r   Remove FLAC input file after processing"
+   echo "         -D<dest-path>   Path to output MP3 files (default is ../Mp3)"
+   echo "         -Vn  Set the target bitrate (quality) of LAME VBR encoder"
+   echo "          where n = 0 target bitrate 245 kbit/s"
+   echo "                n = 1 target bitrate 225 kbit/s"
+   echo "                n = 2 target bitrate 190 kbit/s"
+   echo "                n = 3 target bitrate 175 kbit/s"
+   echo "                n = 4 target bitrate 165 kbit/s"
+   echo "                n = 5 target bitrate 130 kbit/s (default)"
+   echo "                n = 6 target bitrate 115 kbit/s"
+   echo "                n = 7 target bitrate 100 kbit/s"
+   echo "                n = 8 target bitrate 85 kbit/s"
+   echo "                n = 9 target bitrate 65 kbit/s"
+   echo ""
+   echo "Converts all *.flac files under <src-path> to MP3 format using LAME encoder"
+   echo "result files are placed to <dest-path>/<src-path>, default is ../Mp3/<src-path>"
+   echo "<src-path> should be a relative path for correct operation"
+}
+
+# Print diagnostic and error messages to stderr
+# $1: diagnostic level. Message printed if parameter <= set debug level
+# $2: message to be printed
+#
+printmsg ()
+{
+   if [ $(($1)) -le $((DBG_LEVEL)) ]
+   then
+      (>&2 echo "$2")
+   fi
+}
+
+
+# Traverse directory trees
+# $1: source path
+# $2: dest path
+#
+function traverse()
+{
+   for file in "$1"/* ; do
+      if [ ! -d "${file}" ]
+      then
+         printmsg 2 "__Checking file: ${file} for processing, extension: ${file##*.}"
+         if [ "${file##*.}" = "flac" ]
+         then
+            printmsg 1 "__File ${file} is a FLAC file and to be processed"
+            if [ ! -e "$2/${file%.*}.mp3" ]
+            then
+               printmsg 0 "__Converting file: ${file%.*}.flac"
+               printmsg 1 "__Destination file: $2/${file%.*}.mp3"
+               convertf2m "${file%.*}" "$2/${file%.*}"
+            else
+               printmsg 1 "__No conversion: $2/${file%.*}.mp3 exists"
+            fi
+         fi
+      else
+         printmsg 2 "__${file} is a directory, entering recursively"
+         printmsg 1 "__Checking existense of $2/${file}"
+         if [ ! -e "$2/${file}" ]
+         then
+            printmsg 2 "__Destination directory $2/${file} does not exist"
+            COUNTFILES=`ls -1 "${file}"/*.* 2>/dev/null | wc -l`
+            COUNTFLAC=`ls -1 "${file}"/*.flac 2>/dev/null | wc -l`
+            if [ $COUNTFILES == 0 ] || [ $COUNTFLAC != 0 ]
+            then
+               CRPATH="$2/${file}"
+               CRDIRSCRIPT=$(mktemp)
+               printmsg 0 "__Creating directory: $CRPATH"
+               echo "mkdir \"$CRPATH\"" >"$CRDIRSCRIPT"
+               chmod 700 "$CRDIRSCRIPT"
+               "$CRDIRSCRIPT"
+               rm "$CRDIRSCRIPT"
+            else
+               printmsg 1 "__Directory $2/${file} not created as source not empty and does not have FLAC files, files: $COUNTFILES, FLACs: $COUNTFLAC"
+            fi
+         else
+            printmsg 2 "__Directory $2/${file} exists"
+         fi
+         traverse "${file}" "$2"
+      fi
+   done
+}
+
+# Convert single FLAC file to Mp3
+# $1: source file with path (without .flac extension)
+# $2: destination file with path (without .mp3 extension)
+#
+convertf2m ()
+{
+   declare -i RESULT
+   declare -i COVEREXIST
+
+   printmsg 0 "============================================================"
+   printmsg 0 "File to be processed: $1.flac"
+   OUTF=$2.mp3
+   printmsg 0 "Output file name:    `basename "$OUTF"`"
+   
+   printmsg 0 "-------------------- Source tags ---------------------------"
+   ALBUM=`metaflac "$1.flac" --show-tag=ALBUM | sed s/.*=//g`
+   printmsg 0 "Album:                       <$ALBUM>"
+   ALBUMARTIST=`metaflac "$1.flac" --show-tag=ALBUMARTIST | sed s/.*=//g`
+   if [ -n "$ALBUMARTIST" ]
+   then
+      printmsg 0 "Album artist:                <$ALBUMARTIST>"
+   fi
+   ARTIST=`metaflac "$1.flac" --show-tag=ARTIST | sed s/.*=//g`
+   printmsg 0 "Artist:                      <$ARTIST>"
+   BAND=`metaflac "$1.flac" --show-tag=BAND | sed s/.*=//g`
+   if [ -n "$BAND" ]
+   then
+      printmsg 0 "Band/orchesra:               <$BAND>"
+   fi
+   COMMENT=`metaflac "$1.flac" --show-tag=COMMENT | sed s/.*=//g`
+   if [ -n "$COMMENT" ]
+   then
+      printmsg 0 "Comment:                     <$COMMENT>"
+   fi
+   COMPOSER=`metaflac "$1.flac" --show-tag=COMPOSER | sed s/.*=//g`
+   if [ -n "$COMPOSER" ]
+   then
+      printmsg 0 "Composer:                    <$COMPOSER>"
+   fi
+   DATE=`metaflac "$1.flac" --show-tag=DATE | sed s/.*=//g`
+   if [ -n "$DATE" ]
+   then
+      printmsg 0 "Date:                        <$DATE>"
+   fi
+   DISCNUMBER=`metaflac "$1.flac" --show-tag=DISCNUMBER | sed s/.*=//g`
+   if [ -n "$DISCNUMBER" ]
+   then
+      printmsg 0 "Disc #:                      <$DISCNUMBER>"
+   fi
+   GENRE=`metaflac "$1.flac" --show-tag=GENRE | sed s/.*=//g`
+   if [ -n "$GENRE" ]
+   then
+      printmsg 0 "Genre:                       <$GENRE>"
+   fi
+   TITLE=`metaflac "$1.flac" --show-tag=TITLE | sed s/.*=//g`
+   printmsg 0 "Title:                       <$TITLE>"
+   TOTALDISCS=`metaflac "$1.flac" --show-tag=TOTALDISCS | sed s/.*=//g`
+   if [ -n "$TOTALDISCS" ]
+   then
+      printmsg 0 "# of Discs:                  <$TOTALDISCS>"
+   fi
+   TOTALTRACKS=`metaflac "$1.flac" --show-tag=TOTALTRACKS | sed s/.*=//g`
+   if [ -n "$TOTALTRACKS" ]
+   then
+      printmsg 0 "# of Tracks:                 <$TOTALTRACKS>"
+   fi
+   TRACKNUMBER=`metaflac "$1.flac" --show-tag=TRACKNUMBER | sed s/.*=//g`
+   printmsg 0 "Track #:                     <$TRACKNUMBER>"
+   YEAR=`metaflac "$1.flac" --show-tag=YEAR | sed s/.*=//g`
+   if [ -n "$YEAR" ]
+   then
+      printmsg 0 "Year:                        <$YEAR>"
+   fi
+
+   if [ -n "$ALBUMARTIST" ]
+   then
+      TPE2=$ALBUMARTIST
+   else
+      if [ -n "$BAND" ]
+      then
+         TPE2=$BAND
+      else
+         TPE2=$ARTIST
+      fi
+   fi
+   if [ -n "$DATE" ]
+   then
+      TYER=$DATE
+   else
+          if [ -n $YEAR ]
+               then
+         TYER=$YEAR
+      fi
+   fi
+   TALB=$ALBUM
+   TPE1=$ARTIST
+   TRCK=$TRACKNUMBER
+   TIT2=$TITLE
+   TCON=$GENRE
+   COMM=$COMMENT
+   if [ -n "$DISCNUMBER" ]
+   then
+      TPOS=$DISCNUMBER
+   else
+      TPOS="1"
+   fi
+   if [ -n "$TOTALDISCS" ]
+   then
+      TPOS="$TPOS/$TOTALDISCS"
+   else
+      TPOS="$TPOS/1"
+   fi
+   COVEREXIST=0
+   for img in "$TPE2 - $TALB" "$TALB" "cover" "Cover" "folder" "Folder" "front" "Front" 
+   do
+      for ext in "jpg" "gif" "png"
+      do
+         COVERFILE="`dirname "$1"`/"$img"."$ext""
+         printmsg 2 "Trying: $COVERFILE"
+         if [ -e "$COVERFILE" ]
+         then
+            COVEREXIST=1
+            break
+         fi
+      done
+      if [ $COVEREXIST -eq 1 ]
+      then
+         printmsg 1 "Cover image file found:      <`basename "$COVERFILE"`>"
+         APIC=$COVERFILE
+         break
+      fi
+   done
+   if [ $COVEREXIST -eq 0 ]
+   then
+      printmsg 0 "Cover image file:            <-none->"
+   fi
+
+   printmsg 0 "-------------------- Output tags ---------------------------"
+   printmsg 0 "TPOS (Disc number):          <$TPOS>"
+   printmsg 0 "TPE2 (Album artist/band):    <$TPE2>"
+   printmsg 0 "TALB (Album):                <$TALB>"
+   printmsg 0 "TRCK (Track number):         <$TRCK>"
+   printmsg 0 "TPE1 (Track artist):         <$TPE1>"
+   printmsg 0 "TIT2 (Track title):          <$TIT2>"
+   printmsg 0 "TCON (Genre):                <$TCON>"
+   printmsg 0 "TYER (Album date/year):      <$TYER>"
+   printmsg 0 "COMM (Comment):              <$COMM>"
+   if [ $COVEREXIST -eq 1 ]
+   then
+      printmsg 0 "APIC (Cover art file):       <`basename "$APIC"`>"
+   else
+      printmsg 0 "APIC (Cover art file):       <-none->"
+   fi
+   printmsg 0 ""
+
+   LAMEPARAMS="--ta \"${TPE1}\" --tl \"${TALB}\" --tn \"$TRCK\" --tt \"$TIT2\" "
+   if [ -n "$TPOS" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --tv TPOS=\"$TPOS\""
+   fi
+   if [ -n "$TPE2" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --tv TPE2=\"$TPE2\""
+   fi
+   if [ -n "$TCON" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --tg \"$TCON\""
+   fi
+   if [ -n "$TYER" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --ty \"$TYER\""
+   fi
+   if [ -n "$COMM" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --tc \"$COMM\""
+   fi
+   if [ -n "$APIC" ]
+   then
+      LAMEPARAMS="$LAMEPARAMS --ti \"$APIC\""
+   fi
+
+   LAMEPARAMS="flac -c -d \"$1.flac\" | lame  -V$LAME_VBR --add-id3v2 --pad-id3v2 $LAMEPARAMS - \"$OUTF\""
+   LAMESCRIPT=$(mktemp)
+   printmsg 2 "Temporary file for lame parameters: $LAMESCRIPT"
+   echo $LAMEPARAMS > $LAMESCRIPT
+   chmod 700 $LAMESCRIPT
+   $LAMESCRIPT
+   RESULT=$?
+   RESULTALL=$RESULTALL+$RESULT
+   if [ $RESULT = 0 ]
+   then
+      printmsg 0 "Current operation result: OK ($RESULT)"
+   else
+      printmsg 0 "Current operation result: *** Error *** ($RESULT)"
+      cat "$LAMESCRIPT"
+   fi
+   if [ -e "$LAMESCRIPT" ]
+   then
+      rm $LAMESCRIPT
+   fi
+   if [ $FLAC_DELETE -eq 1 ] && [ $RESULT -eq 0 ]; then
+      rm "$1.flac"
+      printmsg 0 "Input file $1.flac deleted."
+   fi
+   (( NUMFILES++ ))
+}
+
+NO_ARGS=0
+E_OPTERROR=85
+FLAC_DELETE=0
+MP3PATH="../Mp3"
+LAME_VBR=5
+DBG_LEVEL=0
+declare -i RESULTALL
+declare -i NUMFILES
+RESULTALL=0
+NUMFILES=0
+
+echo "$(basename $0) [$VERSION] - FLAC to MP3 conversion script"
+# Test if script invoked without command-line arguments
+if [ $# -eq "$NO_ARGS" ]
+then
+   print_usage
+   exit $E_OPTERROR
+fi
+
+while getopts "d:rhD:V:" OPTION
+   do
+      case $OPTION in
+         d ) if [ "$OPTARG" -ge 0 ] && [ "$OPTARG" -le 2 ]
+            then
+               DBG_LEVEL=$OPTARG
+               echo "Debug level is set to $DBG_LEVEL"
+            else
+               print_usage
+            fi;;
+         r ) FLAC_DELETE=1
+             printmsg 0 "FLAC source files will be deleted after conversion";;
+         h ) print_usage;;
+         D ) MP3PATH=$OPTARG
+            printmsg 0 "MP3 output files will be written directory (relative to source dir): $MP3PATH";;
+         V ) if [ "$OPTARG" -ge 0 ] && [ "$OPTARG" -le 9 ]
+            then
+               LAME_VBR=$OPTARG
+               printmsg 0 "LAME VBR quality is set to $LAME_VBR"
+            else
+               print_usage
+            fi;;
+      esac
+   done
+shift $(($OPTIND - 1))
+
+traverse $1 $MP3PATH
+
+printmsg 0 "============================================================"
+printmsg 0 "Conversion complete"
+printmsg 0 "Files processed: $NUMFILES"
+if [ $RESULTALL = 0 ]
+then
+    printmsg 0 "Conversion process result: OK ($RESULTALL)"
+else
+    printmsg 0 "Conversion process result: *** Error *** ($RESULTALL)"
+fi
+
+exit $RESULTALL