Compressing my audio library


After a few years of collecting music on various platforms, mostly Bandcamp, my music libraries have grown to some degree.

My remote music library (sitting behind a Navidrome instance) is about 100Gb; the local one being roughly the same size.

The majority are stored in lossless formats like FLAC or WAV with other formats in the mix, which brings the size up quite a bit.

While talking to a friend, the Opus recommended settings page was mentioned and I started toying around with ffmpeg to see how low I could get.

To give some numbers, I started with a bitrate of 128k which brought down the size quite a lot already. Let’s do a first test using the Lost Eden Soundtrack, which scores at 2.2Gb in the WAV format. After running the conversion, we are now at 67Mb, a reduction of around 188%.

 jae@thetys  ~/music-convert  du -sh *
2.2G    in
67M     out
Zsh

However, 128k is the music storage recommendation, what if we went with the streaming recommended of 96k?

This time the difference doesn’t seems much from the previous result, scoring at 51Mb, not much gained, but still an impressive 190% difference.

 jae@thetys  ~/music-convert  du -sh *
2.2G    in
51M     out
Zsh

After converting my whole remote library, storage now stands around 18Gb, which a good reduction from the original 100Gb.

The script itself is fairly simple as well:

SRC="/home/jae/music-convert/in"
DST="/home/jae/music-convert/out"
JOBS=20

export SRC DST

find "$SRC" -type f -print0 |
  xargs -0 -P "$JOBS" -I {} bash -lc '
  in="$1"
  rel="${in#$SRC/}"
  ext="${in##*.}"
  ext_lc="$(printf "%s" "$ext" | tr "[:upper:]" "[:lower:]")"

  case "$ext_lc" in
    jpg|jpeg|png|webp|gif|bmp|webp|jxl|avif)
      out="$DST/$rel"
      mkdir -p "$(dirname "$out")"
      cp -p "$in" "$out"
      exit 0
      ;;
  esac

  out="$DST/${rel%.*}.ogg"
  mkdir -p "$(dirname "$out")"

  ffmpeg -hide_banner -loglevel error -nostdin -y \
    -i "$in" \
    -map 0:a:0? \
    -map_metadata 0 \
    -c:a libopus -b:a 96k -vbr on -compression_level 10 \
    -c:v copy \
    "$out"
' bash "{}"
Bash

We specify the in and out directories, then find will iterate through all the files and try to convert them. There’s also a small step to reproduce the file hierarchy when converting whole libraries.

There’s also the special case of album covers that I wanted to keep around, so those are just copied over.

The ffmpeg command either isn’t magical, just map the metadata, and use libopus to convert the file to 96k. There are 20 instances launched in parallel which seems to run well on my machine.

So far, it’s been working great with no noticeable changes in the audio quality; this saves up on storage, but also computing since my instance won’t have to transcode files on demand that much any more.


Jae's Blog
Jae's Blog
@b@b.j4.lc

Jae’s blog, now federating properly!

140 posts
43 followers

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *