You are here

Automatically rip audio cd's

Whenever I buy a new audio cd I use my laptop to rip the music to disk and place it on my server so that we can listen to it using a Raspberry Pi with Kodi. So, I bought myself an new and shiny laptop... but the thing does not have a cd/dvd-player! Oops... now what? Keep my old laptop just for cd ripping purposes?

I figured it would be kinda cool to attach an old usb DVD-player to the Raspberry Pi and make it rip the contents of every audio cd inserted automatically.

So, I created an udev-rule that triggers a bash-script whenever an audio-cd is inserted into the drive:

osmc@osmc:~$ cat /etc/udev/rules.d/50-jacktheripper.rules 
ACTION=="change", KERNEL=="sr[0-9]*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_AUDIO}!="", ENV{ID_CDROM_MEDIA_TRACK_COUNT_AUDIO}!="0", RUN+="/usr/local/bin/jacktheripper.sh '%E{DEVNAME}'"

Then I created a shell-script that automatically rips all tracks of the inserted cd and places it on my server. This script however was killed by udev before it finished ripping the first track, so I made the script schedule itself via the at-command so it would not be under the control of udev anymore.

Here's the script:

#!/bin/bash

# Do not run twice... (the script is called jacktheripper.sh)
ps aux | grep -v $$ | grep -q jacktherippe[r] && exit 1

# Don't run if no argument is given
if [ "$1" == "" ]; then
  echo "Please provide a device-name"
  exit 1
fi

# I need to schedule myself through 'at' because of udevs' timeout
if [ "$2" != GO ]; then
  echo $0 $1 GO | at now
  exit 0
fi

# mount a server share to write on and open it
if ! grep -q jacktheripper /proc/mounts; then
  mount -t cifs -o username=******,password=****** //192.168.2.250/public /mnt/jacktheripper || exit 1
fi

# Open the server share
cd /mnt/jacktheripper || exit 1

# Create a temporary directory for ripping the inserted disc
mkdir rip$$
cd rip$$ || exit 1

# rip the disc's contents and fetch cddb-info
icedax -L 0 -B -D $1

# Write to logfile which can be picked-up by the flac conversion-script
echo $$ >> /mnt/jacktheripper/jacktheripper.log

# Eject the disc and unmount the server share
cd ~
umount /mnt/jacktheripper
eject $1

After the script finishes it writes the 'id' of the rip (simply the pid of the script) to a log so that another script on the fileserver can pick it up and convert it into flac files. I tried to do this directly in the above script but the pi is just too slow for this job (it's a first-gen).

The script on the fileserver looks like this:

#!/bin/bash

[ -f /mnt/public/jacktheripper.log ] || exit 1
[ -f /mnt/public/jacktheripper.log.1 ] && exit 1
mv /mnt/public/jacktheripper.log /mnt/public/jacktheripper.log.1
for id in $(</mnt/public/jacktheripper.log.1); do

  # Try to open the directory with this id
  cd /mnt/public/rip$id || exit 1

  # Get album information
  albumartist=$(grep Albumperformer audio_01.inf | cut -d"'" -f2- | sed "s/'$//g")
  album=$(grep Albumtitle audio_01.inf | cut -d"'" -f2- | sed "s/'$//g")
  year=$(grep DYEAR audio.cddb | cut -d'=' -f2)
  genre=$(grep DGENRE audio.cddb | cut -d'=' -f2)

  # Create the directory for this album
  mkdir -p "$albumartist/$album" || exit 1

  # Convert all .wav files to .flac
  for track in *wav; do
    # Get track-specific information
    infofile=${track%%wav*}inf
    artist=$(grep ^Performer $infofile | cut -d"'" -f2- | sed "s/'$//g")
    title=$(grep Tracktitle $infofile | cut -d"'" -f2- | sed "s/'$//g")
    tracknumber=$(grep Tracknumber $infofile | awk '{print$2}')

    # prepend a zero if the tracknumber is <10
    if [ ${#tracknumber} == 1 ]; then
      tracknumber=0$tracknumber
    fi

    # Convert the .wav to .flac
    flac -8 $track -o "$albumartist/$album/$tracknumber - $title.flac" || exit 1

    # Add metadata to the file
    metaflac --set-tag=ARTIST="$artist" "$albumartist/$album/$tracknumber - $title.flac"
    metaflac --set-tag=ALBUM="$album" "$albumartist/$album/$tracknumber - $title.flac"
    metaflac --set-tag=TITLE="$title" "$albumartist/$album/$tracknumber - $title.flac"
    metaflac --set-tag=TRACKNUMBER="$tracknumber" "$albumartist/$album/$tracknumber - $title.flac"
    metaflac --set-tag=GENRE="$genre" "$albumartist/$album/$tracknumber - $title.flac"

  done

  # Move converted files to our music collection
  if [ -d "/mnt/public/Muziek/$albumartist" ]; then
    mv "$albumartist/$album" "/mnt/public/Muziek/$albumartist/$album"
  else
    mv "$albumartist" "/mnt/public/Muziek/$albumartist"
  fi

  # Remove original rip
  if [ "$?" == "0" ]; then
    cd ~
    rm -rf /mnt/public/rip$id
  fi

done && rm -f /mnt/public/jacktheripper.log.1

This script converts all .wav files to .flac and moves the converted files into our music collection. After that it removes the original rip from disk.

So, I put in a audio disc, wait until it gets ejected again. Then wait a few minutes for the fileserver to generate the flac-files and start to listen! :-)