Musical Janitor
I have an extensive collection of music, collected over many years. This collection has grown at a faster rate since discovering bandcamp.com from where I've bought a lot of (great) music.
But sometimes this music is in some silly high sample rate (which is snakeoil), and it rarely contains the replaygain tags that I'd like.
So I typically hack a simple script together to go through the collection, transcode down to good old 44.1KHz/16bit and add replaygain tags if necessary. This is my third or forth iteration, as I never ever save these scripts anywhere before moving between systems, operating systems or distributions.
This should be 'portable', given that you install the dependencies (FLAC, GNU Parallel). It only checks the samplerate (and ignores the bitrate) but it's Good Enough™. It will run on all your available cores for the heavy tasks1, not bad for a script thrown together just before bedtime eh?
Update 2023: Cleaned up the script, added systemd service and timer.
janitor.sh
I just save it as ~/.local/bin/janitor.sh
and make it executable, it should be automagically in your path with most shells.
#!/usr/bin/env bash
type metaflac &>/dev/null || echo "metaflac not installed"
type parallel &>/dev/null || echo "paralell not installed"
type ffmpeg &>/dev/null || echo "ffmpeg not installed"
# Optional but I like it
type fdfind &>/dev/null || echo "fdfind not installed"
function cleanup {
[[ -f /tmp/replaygain-folders ]] && rm /tmp/replaygain-folders
[[ -f /tmp/transcode-candidates ]] && rm /tmp/transcode-candidates
[[ -f /tmp/all-flac-files ]] && rm /tmp/all-flac-files
}
trap "cleanup" EXIT SIGQUIT SIGTERM
# find /tank/media/music -name "*.flac" | grep -v "._" > /tmp/all-flac-files
fdfind -e flac . /tank/media/music > /tmp/all-flac-files
if [ -f /tmp/all-flac-files ]; then
parallel '
if ! $(metaflac --show-sample-rate {} | grep -qi 44100); then
echo {} >> /tmp/transcode-candidates
fi
if ! $(metaflac --list --block-type=VORBIS_COMMENT {}|grep -qi replaygain); then
echo {//} >> /tmp/replaygain-folders
fi
' < /tmp/all-flac-files
echo "Files scanned..."
fi
if [ -f /tmp/transcode-candidates ]; then
parallel '
transcoded=`mktemp -d`
if (ffmpeg -i {} -ar 44100 -sample_fmt s16 $transcoded/{/}) 2>/dev/null; then
cp $transcoded/{/} {//}
rm -rf "${transcoded}"
fi
' < /tmp/transcode-candidates
echo "Transcode candidates handled..."
fi
if [ -f /tmp/replaygain-folders ]; then
parallel '
pushd {}
metaflac --add-replay-gain *.flac
popd
' < /tmp/replaygain-folders|sort|uniq
echo "Replaygain applied. Done."
fi
systemd
I run these as a normal user account. Create the necessary folders if not already present:
mkdir -p ~/.config/systemd/user
Save this as ~/.config/systemd/user/janitor.service
[Unit]
Description=Musical janitor
After=network.target
[Service]
Type=oneshot
WorkingDirectory=%h
ExecStart=%h/.local/bin/janitor.sh
[Install]
WantedBy=default.target
And save this as ~/.config/systemd/user/janitor.timer
and adjust the timers as needed:
[Unit]
Description=Run our musical janitor weekly
[Timer]
# Run 31 minutes after boot, and then once every week
OnBootSec=31min
OnUnitActiveSec=1w
[Install]
WantedBy=timers.target
Finally, enable the timer and it should start scanning the library, and then run it on the schedule specified in the timer file:
$ systemctl --user enable --now janitor.timer
# [...]
$ systemctl --user status janitor.timer
● janitor.timer - Run our musical janitor weekly
Loaded: loaded (/home/oscar/.config/systemd/user/janitor.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Wed 2023-05-09 21:26:20 CEST; 13min ago
Trigger: Wed 2023-05-16 21:26:20 CEST; 6 days left
Triggers: ● janitor.service
maj 09 21:26:20 atomic systemd[28333]: Started Run our musical janitor weekly.
And dear GNU Parallel author, I will cite you if I ever use Parallels in an academic context. I promise.