I was talking with a friend a few days ago because they posted about how much space storing music takes up, when I decided that I ought to write down how I do my music library’s organization.
Now, ideally this might not be that interesting, but I don’t have much storage space, and I don’t wish to store lossless music on everything. I just don’t have the storage space across all my devices.
somasis ~ ● ssh fort beet stats
Tracks: 11983
Total time: 4.9 weeks
Approximate total size: 329.7 GiB
Artists: 1964
Albums: 984
Album artists: 337What I can do, is store lossless in one place, and then store compressed copies everywhere else, though. Here’s how I do that.
When I get my music, I store it in a directory on a server in my
home. This directory is the source,
“/mnt/raid/library/audio/source”.
somasis ~ ● ssh fort tree /mnt/raid/library/audio/source --dirsfirst -d -L 1
/mnt/raid/library/audio/source
|-- rips
| |-- Various Artists - Hot Wheels Turbo Racing (1999)
| |-- Various Artists - Inner City Sounds
| `-- Various Artists - Little Darla has a Treat for You, Volume 30 - Summer 2020
|-- stores-bandcamp
| |-- ATW - A Small Horse
| |-- ATW - Mares EP
| |-- Andrew Lang - Burnt Shades
| |-- Andrew Lang - From Before
| |-- Andrew Lang - Momentary Senses
| |-- Andrew Lang - Strangers EP
| |-- Karnaboy - Feathers Falling in Slow Motion
| `-- Men I Trust - Oncle Jazz
[...]And so on.
It is where all the things in the library originate from, in terms of import location. Additionally, tracking details like if I ripped it from my CD collection/vinyl collection, or if it was from Bandcamp, helps me to retrace my steps if I notice issues on a MusicBrainz release I committed. Mainly, this allows for an incremental import, using the corresponding configuration options in beets, meaning that it won’t import from any directories it has already imported from in the past.
I have a simple Makefile for importing, which simply
runs…
beet-import:
find /mnt/raid/library/audio/source \
-mindepth 2 \
-maxdepth 2 \
-type d \
-exec beet import -tc {} +Again, it’s using the -{min,max}depth so as to catch all
the categorizing directories ("stores-*", "rips"), but nothing under
them.
When I get a new music release, I put it in the corresponding source
directory, and run make beet-import.
I run the interactive tagger, rather than let it do anything here
automatic, and I run beet import -t; so, using "timid"
mode, to be even more pedantic. My goal is for beets to be the source of
truth when it comes to what my music library contains. If a single thing
is linked to a release other than what it actually is, it invalidates my
trust in the accuracy of my entire library’s tagging. Accuracy is
important for me, as someone who has a lot of music and uses much of it
when producing more music. So, I run it in timid mode and
validate the results myself.
The music is imported to “/mnt/raid/library/audio/lossless”. I like
to keep the directory mounted over sshfs, so I can access
it from “~/audio/lossless” on my laptop.
The relevant beets config.yml snippet:
convert:
copy_album_art: yes
album_art_maxwidth: 800
embed: no
never_convert_lossy_files: yes
formats:
opus:
command: ffmpeg -i $source -y -vn -acodec libopus -ab 96k -ar 48000 $dest
extension: opusWhich is to say…
embed:no, copy_album_art: yes: No embedding the
artwork, it takes up more space since it duplicates the art for
every single track you store. Copy it instead, to
"cover.jpg".album_art_maxwidth: 800: The cover art for Minecraft,
Volume Alpha, is 2676x2676. I assure you my phone doesn’t need that
resolution.never_convert_lossy_files: yes: No converting files
that are already a lossy format (which for me tends to be mp3s, because
pony music is always released in a bespoke fashion).opus. I use 96k Opus, and the -ar 48000
looks unnecessary, but actually is not: it’s to make sure I
don’t have a 96kHz rip of something converted to Opus, with the codec
happily supporting a sample rate that large. So just homogenize
everything down to 48k, Opus’s default sample rate.Which brings us to the second Makefile target:
beet-convert:
beet convert -a -f opus -yI wish I could just stop there and say that’s how I maintain the two
copies of my library, but alas. We have arrived upon the first problem
with beet convert.
Though beets’s homepage proudly
displays the beet convert
plugin for transcoding audio to any format desired, it does not do the
upkeep of maintaining a library’s structure in the process as
well.
The problem lies in removing and renaming tracks. beets will shift
files in your library directory (which in my case is the lossless
directory) without issue most of the time, but it is not smart enough to
replicate those changes on the libraries maintained with
beet convert
Really, the main problem is that beet convert (and
beet alternatives) only do the work of creating the
structure-- once folders change, filenames change, the problem is then
that you have duplicates, and you’ll have the converted library
structure fall out of sync over time if you want to keep the same
directory structure.{fn-structure}
As of now, I fix this problem with a little script named beet-rmdupes;
it also requires the mimefilter
script in my "~/bin" as well. It’s a little wonky in terms of false
positives when it comes to beets' asciification, for reasons I have not
yet figured out.
This is essentially the hard parts. The rest is pretty standard beets configuration, and the documentation is otherwise excellent, except for these particularly irritating pitfalls.
beets does… a staggering amount, and without choking as hard as it could. I’ve really considered writing my own music managing utility as of late but I just haven’t had the motivation to uproot my library again.
However, there’s bits and pieces laying around… someday.
2021-05-21