Ubuntu: Automatically rip CD to FLAC and convert to ALAC m4a for iTunes & HomeSharing




Since getting iTunes running smoothly on my Ubuntu server under VirtualBox I was looking to upgrade and automate my CD ripping process. My aim here was to have a near 'zero click' approach for ripping an inserted CD to FLAC for opensource goodness and then to convert the files to ALAC for iTunes compatibility and HomeSharing. The two click solution I've reached involves 1) to select the right CD metadata from an CD info site and 2) to hit the button to rip, the script does the rest. It now takes me under 15 minutes to rip a CD to FLAC and get it into iTunes and shared over HomeSharing with just two clicks, here's how...


N.B. As of October 2011 ALAC is now open source too.



This post will use:

sound-juicer - a CD ripping tool which I believe is native to Ubuntu 10.04 and has a very clean user interface;
ffmpeg - a transcoding tool used here to transcode FLAC to ALAC 
and also includes the ALAC codec suite;
metaflac - a meta data reader specific to FLAC used here to read the FLAC meta data to write to ALAC.
 

Before I dive into automation script you will need to setup sound-juicer to suit your needs, with the appropriate default file paths to rip to, format and quality settings; I use FLAC. I won't cover setting soud juicer up here, since it's pretty straight forward. To open sound juicer run sound-juicer from the terminal.

Now onto the concept of the script, which does the following steps as part of the automated process:

1) Automatically check for and install sound-juicer, ffmpeg and metaflac no further configuration of these are required;
2) Run sound-juicer and let you select the cd metadata from a database and click 'Extract' to extract;
3) Close sound-juicer after extracting all of your CD's for the conversion to take place;
4) Capture the metadata from the FLAC file and extract it ready for the ALAC format;
5) Perform the FLAC to ALAC conversion with ffmpeg and the metadata;
6) Move the processed FLAC files into the processed directory;
7) Delete the source directories which have been processed.


Here's how to implement the script in 5 steps:

1)  Create a bash script 'CDRip': 

cd /usr/local/bin && gedit /usr/local/bin/CDRip

2) Paste in the bash script from below, editing the blue lines indicated to reflect your file paths:
#!/bin/bash
#This script rips CDs to FLAC using sound-juicer
#It then converts them to ALAC for iTunes and HomeSharing
#It translates the FLAC metadata to the ALAC metadata format
#It also retains the original FLAC file for prosperity


##############################
### SET YOUR PARAMETERS ### 
############################## 



#Set the base directory 
sBASEDIR="/DATA/Music/"

#Set directory sound juicer rips to
sIN="Ripped"

#Set directory ALAC files are placed in
sOUTALAC="Automatically Add to iTunes"

#Set directory converted FLAC files are placed in
sOUTFLAC="Processed"



###################################
### DO NOT EDIT BELOWTHIS LINE ###
###################################

#Check and install flac
problem=$(dpkg -s flac|grep installed)
echo "Checking for flac: $problem"
if [ "" == "$problem" ]; then
     echo "No flac. Setting up flac"
     sudo apt-get --force-yes --yes install flac
fi

#Check and install ffmpeg
problem=$(dpkg -s ffmpeg|grep installed)
echo "Checking for ffmpeg: $problem"
if [ "" == "$problem" ]; then
      echo "No ffmpeg. Setting up ffmpeg"
      sudo apt-get --force-yes --yes install ffmpeg
fi

#Check and install sound-juicer
problem=$(dpkg -s sound-juicer|grep installed)
echo "Checking for sound-juicer: $problem"
if [ "" == "$problem" ]; then
      echo "No sound-juicer. Setting up sound-juicer"
      sudo apt-get --force-yes --yes install sound-juicer
fi

#Start sound-juicer
sound-juicer

###############################
### START ALAC CONVERSION ### 
###############################


#Set up some directory paths based on the variables
sINPATH="$sBASEDIR""$sIN"
sOUTALACPATH="$sBASEDIR""$sOUTALAC"
sOUTFLACPATH="$sBASEDIR""$sOUTFLAC"
echo "Variables set"

#Create ALAC output directory structure
find $sINPATH -type d | sed "s/$sIN/$sOUTALAC/" | xargs -d'\n' mkdir

#Create processed FLAC directory structure, prevents future reprocessing
find $sINPATH -type d | sed "s/$sIN/$sOUTFLAC/" | xargs -d'\n' mkdir

#Capture the FLAC meta data for conversion to ALAC metadata
for i in "$sINPATH"/*/*/*.flac
do

ARTIST=`metaflac "$i" --show-tag=ARTIST | sed s/.*=//g`
TITLE=`metaflac "$i" --show-tag=TITLE | sed s/.*=//g`
ALBUM=`metaflac "$i" --show-tag=ALBUM | sed s/.*=//g`
GENRE=`metaflac "$i" --show-tag=GENRE | sed s/.*=//g`
TRACKTOTAL=`metaflac "$i" --show-tag=TRACKTOTAL | sed s/.*=//g`
DATE=`metaflac "$i" --show-tag=DATE | sed s/.*=//g`
TRACKNUMBER=`metaflac "$i" --show-tag=TRACKNUMBER | sed s/.*=//g`

#Meta data options source:
#http://multimedia.cx/eggs/supplying-ffmpeg-with-metadata/

#Code to echo the metadata for debugging
#echo $ARTIST
#echo $TITLE
#echo $ALBUM
#echo $GENRE
#echo $TRACKTOTAL
#echo $DATE
#echo $TRACKNUMBER

#Set the array of files to process along with their output path
o="${i/$sIN/$sOUTALAC}"

#Set the array of files to process along with their new files extension
o=""${o/.flac/.m4a}""

#Echo the files that will be processed to check in debugging
o=""$(echo $o | sed 's/_//g')""

#Construct the filepath for the first file in the array to process
filepath=${i%/*}

#Construct the filename for the first file in the array to process
filename=${i##*/}

#Echo the path and file name to the terminal for debugging
echo $i
echo $o

#Start the convrsion of file i in the array to ALAC with the metadata
echo "n" |  ffmpeg -i "$i" -metadata title="$TITLE" -metadata author="$ARTIST" -metadata album="$ALBUM" -metadata year="$DATE" -metadata track="$TRACKNUMBER" -acodec alac "$o" 

#Move the ripped file that has been processed to the coverted file directory to stop ffmpeg trying to process the file again in future
d="${i/$sIN/$sOUTFLAC}"
mv "$i" "$d"
done

#Finally after all files have been processed delete the empty source ripped directories of the files which have been processed, which now reside in the converted folder and ALAC folder
for FOLDER in $sINPATH/*
    do
    rm -r "$FOLDER"
    done
exit;


3) Save the script and set it to be executable

sudo chmod 555 /usr/local/bin/CDRip

4) Test the script manually for the first time, this will ensure you have all of the packages installed

CDRip

5) If you want to set the script to be the default action upon insertion of an audio CD, then within Nautilus (the file Ubuntu browser for 10.04 at least) select:

Edit > Preferences > File Manager Preferences > Media > CD Audio

Point this to open your CDRip script! Job done.


I am keen to update this script to move away from Sound-Juicer to something that supports exact audio copy. At this time ruby-ripper is the closest package I am aware of that gets close to this requirement, where I understand that ruby-ripper will continue to rip a CD as many times as you specify in order to get the best copy it can however, I am not convinced it acts like the Windows tool EAC which will continue to rip a disc until it has a bit perfect copy performing a parity check.


This guide builds on and references:
Nighto's metadata work here http://nighto.net/convertendo-flac-para-alac/
Multimedia Mike's metadata work here  http://multimedia.cx/eggs/supplying-ffmpeg-with-metadata/


5 comments:

  1. Since this is a shell script, why aren't you using something like abcde instead of Sound Juicer?

    ReplyDelete
  2. I liked the simple GUI of sound-juice to select the CD metadata from an online database. I want to update this eventually to move toward ruby-ripper to get closer to exact audio copy rips.

    You can adjust the script to use whatever ripper you want, the script just relies on extracted flac files for conversion to alac.

    Swap this line for the ripper of your choice

    #Start sound-juicer
    sound-juicer

    ReplyDelete
  3. I'm not familiar with abcde but it doesn't look like it supports FLAC(?)

    ReplyDelete
  4. abcde does support flac.
    http://www.andrews-corner.org/abcde.html#flac

    ReplyDelete
  5. Thanks for the correction always useful to know. I'm currently using Exact Audio Copy in Wine for extraction until I can find a Linux equivalent. I still like using a GUI based ripper to have the opportunity to select the correct meta data before extraction.

    ReplyDelete