Like many people I prefer to manage my music collection myself instead of leaving it up to something like iTunes. Thankfully iTunes (which you must use if you have certain devices) allows manual copying of music to a device.

The one real problem I have is most of my music is in the lossless FLAC format. Unfortunately, this isn’t natively supported by Apple devices. I convert my FLAC files to mp3 (highest quality) because mp3 is good enough for a mobile device with earbuds. I also have some files in mp3 format already too but these also need a little bit of work before I put them on the device.

To save space I keep a cover.jpg file in the directory with the music files (arranged by artist/album). When I put the files on the device I want every file to show the cover image for its album. The cover.jpg needs to be embedded into the files themselves.

To help myself prepare my music I wrote two scripts to automate this process (to a certain extent). These scripts cover FLAC to mp3 (tags and all) and adds the cover image to all mp3s.

The first script all-2-mp3.sh does two things. It calls the second script flac-2-mp3.sh (which can be run independently). In addition to calling the flac script all-2-mp3.sh also looks for mp3s copies and adds the cover. Both scripts output the prepared files into a specified output directory. The output directory doesn’t do any type of organization. All files just get dump there. Once done I drag and drop the files into the music directory on my device in iTunes (not into the music library).

all-2-mp3.sh uses eyeD3 to embed the cover image in the mp3s. While flac-2-mp3.sh embeds the image directly during conversion. eyeD3 is not required and if not installed the file will just be copied into the output dir.

The required command line applications that need to be installed are:

  • flac
  • lame
  • eyeD3 (optional)

To protect the “master” files both scripts don’t allow the input and output directory to be the same. Also, the input directory cannot be under the output directory. The output directory is excluded from searching for music files if it is under the input directory.

all-2-mp3.sh

#!/bin/bash

if [[ -z $1 ]]; then
    1="./"
fi
if [[ -z $2 ]]; then
    2="./"
fi

if [[ "$1" == "$2" ]]; then
    echo "input and output dir cannot be the same"
    exit 1
fi

if [[ $1 == $2* ]]; then
    echo "input dir cannot be in output dir"
    exit 1
fi

EYED3=$(which eyed3)

bash $(dirname $0)/flac-to-mp3.sh "$1" "$2"

find "$1" -type f -name "*.mp3" -print0 -not -path "$2" | while IFS= read -r -d '' file; do
    COVER=$(dirname "$file")/cover.jpg
    if [[ ! -f "$COVER" ]]; then
        COVER=""
    fi

    echo "Copying $file"
    cp "$file" "$2"

    if [[ "$EYED3" != "" ]] && [[ $COVER != "" ]]; then
        $EYED3 --to-v2.4 -Q --add-image "$COVER":FRONT_COVER "$2/$(basename "$file")"
    fi
done

flac-2-mp3.sh

#!/bin/bash

if [[ -z $1 ]]; then
    1="./"
fi
if [[ -z $2 ]]; then
    2="./"
fi

if [[ "$1" == "$2" ]]; then
    echo "input and output dir cannot be the same"
    exit 1
fi

if [[ $1 == $2* ]]; then
    echo "input dir cannot be in output dir"
    exit 1
fi

find "$1" -type f -name "*.flac" -print0 -not -path "$2" | while IFS= read -r -d '' file; do
    COVER_OPT="--ti"
    COVER=$(dirname "$file")/cover.jpg
    if [[ ! -f "$COVER" ]]; then
        COVER_OPT=""
        COVER=""
    fi

    echo "Converting and copying $file"

    for tag in TITLE ARTIST ALBUM DATE COMMENT TRACKNUMBER TRACKTOTAL GENRE; do
        eval "$tag="`metaflac --show-tag=$tag "$file" | sed 's/.*=//'`""
    done

    flac -s -cd "$file" | lame $COVER_OPT "$COVER" --silent --id3v2-only -V 0 --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" --ty "$DATE" --tc "$COMMENT" --tn "$TRACKNUMBER/$TRACKTOTAL" --tg "$GENRE" - "$2"/"$(basename "${file%.flac}.mp3")"
done