monotux.tech

Musical Janitor

multimedia

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.

1

And dear GNU Parallel author, I will cite you if I ever use Parallels in an academic context. I promise.