MP3 CD burning shell scripts
A bit of automation in burning CDs for an after-market car radio.
According to the previous owner of my Clio III, the radio was replaced because it discharged the battery once. Apparently it’s common, though I didn’t really check. I do know its not because it was stolen, and that’s good enough for me.
The aftermarket piece of crap in its place is a Sony CDX-S2250. It plays music. It’s also broken in a different way, because it refuses to play along with the battery vs switched positive dichotomy, no matter how I connect it (including correctly), so it’s just wired directly to switched and therefore doesn’t remember settings. This limits the radio to only the stations I can be bothered to tune to on every journey, luckily Dwójka is 105.6, near the top, so I can live with it. The UI is also terrible, though it is definite proof that even terribly designed physical buttons are better than a well designed touch UI. But I digress.
I probably should just dropkick it and get something that can do aux/Bluetooth/USB/cassettes*, but it works juuust well enough for me to not quite bother. What narrowly saves it from the bin is that it supports MP3 CDs.
MP3 CDs are a weird not-quite-standard that some later CD players understand. It refers to Data CDs (the Yellow Book kind) that hold normal computer MP3 files (or ATRAC3plus LOL) that the player can decode. This allows for heavy compression, as instead of the uncompressed CD 44100*2*16 = 1.4112 Mbps bitrate you’re free to crank your favourite codec however hard you want, even 8kbps if you really want.
For example, for a recent road trip I burned a CD-ROM with 700MiB worth of MP3s, totaling 13 hours, 6 minutes, and 50 seconds of audio. This is 9.8 times as much as a traditional 80 minute audio CD.
Before any audiophiles calculate the bitrate and leave for my doorstep to take away all my FLACs, I have to stress that my not that well sound-dampened economy nugget screaming 4 500 RPM pulling 130km/h on the motorway does a swell job of distracting from most audio quality issues. An audiophile environment it is not. The 128kbps-ish is probably overkill still. Besides, I’m not doing critical listening, the music is there to keep my higher brain functions somewhat occupied to stop me from losing my shit while fighting traffic on the same 30km stretch of A1 every single god-damn day and deciding to optimize lifetime petrol expenses with the help of the nearest family car and/or truck. 64kbps would do fine. Anyway.
To generate the MP3s, I have carefully assembled a set of two shell scripts.
To create a CD with my method, prepare a directory. Create
within it a subdirectory, from/, and copy runme.sh and convfile.sh from
the previous cdfication. Then, in from assemble a set of less compressed files
from which the CD will be created. This can be done most easily by symlinking
from your 2TB FLAC collection, for example with
ln -s ~/Music/System\ Of\ A\ Down/2005\ -\ Mezmerize/ from/ in the case of a rip**
of my dad’s SOAD CD, or in a pinch you can copy or download stuff
directly to it (convenient for including less refined tastes with yt-dlp -x).
Lastly, run ./runme.sh. After it is finished, a directory named to/ will
appear, like so:
$ ./runme.sh
ffmpeg version n4.4 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 10.2.0 (GCC)
[... ffmpeg spam ...]
size= 2047kB time=00:02:11.68 bitrate= 127.3kbits/s speed=26.1x
video:0kB audio:2046kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.031406%
size= 3196kB time=00:03:31.33 bitrate= 123.9kbits/s speed=29.4x
video:0kB audio:3195kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.020510%
==================================
Filesize:
33M to
Duration:
00:36:12.08
$ find to
to
to/2005 - Mezmerize
to/2005 - Mezmerize/04 - System of a Down - Cigaro_.mp3
to/2005 - Mezmerize/07 - System of a Down - Violent Pornography_.mp3
to/2005 - Mezmerize/01 - System of a Down - Soldier Side (intro)_.mp3
to/2005 - Mezmerize/09 - System of a Down - Sad Statue_.mp3
to/2005 - Mezmerize/08 - System of a Down - Question!_.mp3
to/2005 - Mezmerize/03 - System of a Down - Revenga_.mp3
to/2005 - Mezmerize/06 - System of a Down - This Cocaine Makes Me Feel Like I___m on This Song_.mp3
to/2005 - Mezmerize/05 - System of a Down - Radio-Video_.mp3
to/2005 - Mezmerize/10 - System of a Down - Old School Hollywood_.mp3
to/2005 - Mezmerize/11 - System of a Down - Lost in Hollywood_.mp3
to/2005 - Mezmerize/02 - System of a Down - B.Y.O.B._.mp3
$
It can then be burnt to a CD. In my case, the laptop I main doesn’t actually
have a disc drive, so I have to walk over to parents’, scp over the output
folder, and then burn it. After labeling it with a permanent marker, I can enjoy
a bit more music during my drives!
Let’s take a closer look at the scripts. The magic happens in convfile.sh,
which contains this:
#!/bin/sh
nofrom=${1#from/}
out=to/"$(echo "${nofrom%.*}" | tr -C '[[:graph:]] ' '_' | tr -s ' ')".mp3
mkdir -p "$(dirname "$out")"
test -f "$out" && echo "Skipped $1" || \
ffmpeg -i "$1" -c:a libmp3lame -q:a 5 -vn "$out"
This script is called with a path to one of the files in from. First it prepares
the output filename, by cropping away the beginning from/, then removing the
extension, then replacing all non-ASCII bytes with _***, removing redundant
spaces, and adding .mp3 at the end. Then it recreates the directory structure,
by creating all needed parent folders with mkdir -p. Then the real magic
happens, after ensuring the file isn’t already converted, it calls ffmpeg to
do all the magic. -i "$1" sets the input file, -c:a libmp3lame makes it use
LAME, wihch is probably the best MP3 encoder available, -q:a 5 sets the
quality to 5, which sounds alright for my needs, -vn (“no video”) ensures
that the embedded cover art doesn’t get copied over, and "$out" marks
the output file. If you actually end up using this script, feel free to
modify it, like by increasing or decreasing the quality passed to -q:a 5
or changing the codec if your target device supports something better, like Opus.
The above script is then ran for every file in from by runme.sh. It is
a separate file so many encodes can be ran in parallel.
#!/bin/bash
find -L from -regextype egrep -iregex '.*\.(flac|m4a|mp3|opus)' -print0 | \
xargs -L1 -P6 -0 ./convfile.sh
echo
echo -e '\033[7m==================================\033[0m'
echo
echo 'Filesize:'
du -sh to
echo 'Duration:'
soxi -T -d to/**/*
It finds every flac, m4a, mp3, and opus file, and runs convfile.sh on it,
up to 6 at the same time. If you have more cores, feel free to increase the
number after -P in the second line. The most important find flag here
is -L, which allows it to traverse symlinks, which makes building to easy.
After all the conversions are done, it prints a separator, and then some
statistics - the total disk usage of the to folder, and the total duration.
Having soxi installed is required for the latter.
With this setup, you can too create MP3 CDs for your own enjoyment. Happy commuting! Or just use Spotify through aux.
* Cassettes can be used as aux inputs, making them a more future-proof audio
format than CDs are.
** I do not condone piracy.
*** I am not sure that this is required, but with the amount of CJK in
my playlists and general jank of such a setup, I opted to play it safe. The radio
has a segmented display anyway, so it couldn’t render them even if it wanted to.