Digitising old audio CDs on a Linux Server
A number of people I know own a number of audio / music CDs. This is great, but unfortunately increasingly laptops aren't coming with an optical drive any more, which makes listening to said CDs challenging. To this end, making a digital copy to add to their personal digital music collections would be an ideal solution.
Recently, I build a new storage NAS (which I'm still in the process of deciding on a filesystem for, but I think I might be going with btrfs + raid1), and the Fractal Design Node 804 case I used has a dedicated space for a slimline DVD writer (e.g. like the one you might find in a car). I've found this to be rather convenient for making digital copies of old audio CDs, and wanted to share the process by which I do it in case you'd like to do it too.
To start, I'm using Ubuntu Server 20.04. This may work on other distributions too, but there are a whole bunch of packages you'll need to install - the names and commands for which you may need to convert for your distribution.
To make the digital copies, we'll be using abcde
. I can't find an updated website for it, but it stands for "A Better CD Encoder". It neatly automates much of the manual labor of digitising CDs - including the downloading of metadata from the Internet. To tidy things up after abcde
has run to completion, we'll be using ffmpeg
for conversion and eyeD3
for mp3 metadata manipulation.
To get started, let's install some stuff!
sudo apt install --no-install-recommends abcde
sudo apt install ffmpeg mkcue eyed3 flac glyrc cdparanoia imagemagick
Lots of dependencies here. Many of them are required by abcde
for various features we'll be making use of.
Next, insert the audio CD into the DVD drive. abcde
assumes your DVD drive is located at /dev/sr0
I think, so if it's different you'll have to adjust the flags you pass to it.
Once done, we can call abcde
and get it to make a digital copy of our CD. I recommend here that you cd
to a new blank directory, as abcde
creates 1 subdirectory of the current working directory for each album it copies. When you're ready, start abcde
:
abcde -o flac -B -b
Here, we call abcde
and ask it to save the digital copy as flac
files. The reason we do this and not mp3
directly is that I've observed abcde
gets rather confused with the metadata that way. By saving to flac files first, we can ensure the metadata is saved correctly.
The arguments above do the following:
-o flac
: Save to flac files-B
: Automatically embed the album art into the saved music files if possible-b
: Preserve the relative volume differences between tracks in the album (if replaygain is enabled, which by default I don't think it is)
It will ask you a number of questions interactively. Once you've answered them, it will get to work copying the audio from the CD.
When it's done, everything should be good to go! However flac files can be large, so something more manageable is usually desired. For this, we can mass-convert our flac files to MP3. This can be done like so:
find -iname '*.flac' -type f -print0 | nice -n20 xargs -P "$(nproc)" --null --verbose -n1 -I{} sh -c 'old="{}"; new="${old%.*}.mp3"; ffmpeg -i "${old}" -ab 320k -map_metadata 0 -id3v2_version 3 "${new}";';
There's a lot to unpack here! Before I do though, let's turn it into a bash function real quick which we can put in ~/.bash_aliases
for example to make it easy to invoke in the future:
# Usage:
# flac2mp3
# flac2mp3 path/to/directory
flac2mp3() {
dir="${1}";
if [[ -z "${dir}" ]]; then dir="."; fi
find "${dir}" -iname '*.flac' -type f -print0 | nice -n20 xargs -P "$(nproc)" --null --verbose -n1 -I{} sh -c 'old="{}"; new="${old%.*}.mp3"; ffmpeg -i "${old}" -ab 320k -map_metadata 0 -id3v2_version 3 "${new}";';
}
Ah, that's better. Now, let's deconstruct it and figure out how it works. First, we have a dir
variable which, by default, is set to the current working directory.
Next, we use the one-liner from before to mass-convert all flac files in the target directory recursively to mp3
. It's perhaps easier to digest if we separate it out int multiple lines:
find "${dir}" -iname '*.flac' -type f -print0 # Recursively find all flac files, delimiting them with NULL (\0) characters
| nice -n20 # Push the task into the background
xargs # for each line of input, execute a command
--null # Lines are delimited by NULL (\0) characters
--verbose # Print the command that is about to be executed
-P "$(nproc)" # Parallelise across as many cores as the machine has
-n1 # Only pass 1 line to the command to be executed
-I{} # Replace {} with the filename in question
sh -c ' # Run this command
old="{}"; # The flac filename
new="${old%.*}.mp3"; # Replace the .flac file extension with .mp3
ffmpeg # Call ffmpeg to convert it to mp3
-i "${old}" # Input the flac file
-ab 320k # Encode to 320kbps, the max supported by ffmpeg
-map_metadata 0 # Copy all the metadata
-id3v2_version 3 # Set the metadata tags version (may not be necessary)
-c:v copy -disposition:v:0 attached_pic # Copy the album art if it exists
"${new}"; # Output to mp3
'; # End of command to be executed
Obviously it won't actually work when exploded and commented like this, but hopefully it gives a sense of how it functions.
I recommend checking that the album art has been transferred over. The -c:v copy -disposition:v:0 attached_pic
bit in particular is required to ensure this happens (see this Unix Stack Exchange answer to a question I asked).
Sometimes abcde
is unable to locate album art too, so you may need to find and download it yourself. If so, then this one-liner may come in handy:
find , -type f -iname '*.mp3' -print0 | xargs -0 -P "$(nproc)" eyeD3 --add-image "path/to/album_art.jpeg:FRONT_COVER:";
Replace path/to/album_art.jpeg
with the path to the album art. Wrapping it in a bash function ready for ~/.bash_aliases
makes it easier to use:
mp3cover() {
cover="${1}";
dir="${2}";
if [[ -z "${cover}" ]] || [[ -z "${dir}" ]]; then
echo "Usage:" >&2;
echo " mp3cover path/to/cover_image.jpg path/to/album_dir";
return 0;
fi
find "${dir}" -type f -iname '*.mp3' -print0 | xargs -0 -P "$(nproc)" eyeD3 --add-image "${cover}:FRONT_COVER:"
}
Use it like this:
mp3cover path/to/cover_image.jpg path/to/album_dir
By this point, you should have successfully managed to make a digital copy of an audio CD. If you're experiencing issues, comment below and I'll try to help out.
Note that if you experience any issues with copy protection (I think this is only DVDs / films and not audio CDs, which I don't intend to investigate), I can't and won't help you, because it's there for a reason (even if I don't like it) and it's illegal to remove it - so please don't comment in this specific case.