djcev.com

//

Music File Management 2: Intake Process and Shell Scripts

Posted by Cameron Vanderzanden on in articles. Source file.
Tags: , , , , .

I've written a number of shell scripts, mostly frontends or shims to other programs, to help manage the tags & content of my music library. In this article I will briefly go over some of those scripts and then give a simple demonstration of how I process & prepare new music files.

The scripts discussed in this article are all available in my read-only dotfiles git repo. (I'll hook up a way to directly download them eventually).

This is part 2 of a series on how I handle my digital music collection. Part 1 covered Formats, Names, and Tags, part 3 will cover playback (and tag editing) with cmus.

Scripts

There are about five scripts I typically use to manage tags on music files. The most important and most frequently used of these is tag_audio.sh, a simple frontend to metaflac and mid3v2. I wrote it because I needed a program with a consistent interface; metaflac and mid3v2 each have their own unique options syntax. Writing my own intermediary script was also an opportunity to codify and standardize what tags I care about and how I view them on-screen.

The short-form help for tag_audio looks like:

Usage: tag_audio.sh [-3fhpV] [-e tag] [-k tag] [-v value] <file>

The options are:

  • -3 and -f to specify the type of <file> (mp3 and flac, respectively)
  • -p to print the tags in <file>
  • -k tag to select tag for editing (option -e is synonymous with -k)
  • -v value to set the selected tag to value

If a tag is selected but no value is supplied, the user will be interactively prompted for a value. If format (-3 or -f) is not supplied then tag_audio will try to guess based on mimetype or file extension. I typically use tag_audio as part of a shell for loop, for instance:

for i in *flac; do tag_audio.sh -k artist -v "DJ CEV" "$i"; done

The script is meant to work on one file at a time, so the final argument must be one filename. Wildcards or multiple files won't work (i.e. tag_audio.sh -p * is no good).

There are three more often-used scripts that follow roughly the same option style outlined above (single file as final argument, -3 and -f to specify mp3 or flac):

  • tag_rg.sh, which calculates & sets a file's replaygain tags (requires metaflac, mid3v2, and mp3gain).
  • tag_key.sh which estimates musical key and sets the key tags on a file (requires metaflac, mid3v2 and key-tools). Option -w tells tag_key to write the key tags on <file>.
  • tag_cover.sh which I use to embed cover images into files (requires metaflac and eyeD3). Accepts option -c to specify an image file to embed as cover artwork.

Last of the five is flac_reencode.sh which decodes and re-encodes flac files. I re-encode to ensure there are no problems with the files, and because I trust the reference encoder more than whatever unknown encoder was used by the source. flac_reencode takes one option, a file or directory; if supplied with a directory it will re-encode every flac file in the specified dir.

Music Files Intake Procedure

Let's go over an easy example session of renaming and tagging some flac files. For demonstration purposes I'm going to re-download & re-process the second Vortex Traks comp (which I picked up during last year's IFM festival). A "..." in these terminal logs indicates that I've shortened some of the input or output lines.

After downloading Various Artists - Vortex Traks Vol. 02.zip I create a directory for the release, unzip, then rename files to fit my standards:

$ mkdir '[vtx003] various - vortex traks vol. 02'
$ ls
[vtx003] various - vortex traks vol. 02
Various Artists - Vortex Traks Vol. 02.zip
$ cd '[vtx003] various - vortex traks vol. 02'
$ unzip ../'Various Artists - Vortex Traks Vol. 02.zip'
 extracting: Kan3da - Vortex Traks Vol. 02 - 01 Dancing Data.flac
 extracting: Morphology - Vortex Traks Vol. 02 - 02 32.flac
...
$ ls
cover.jpg
Kan3da - Vortex Traks Vol. 02 - 01 Dancing Data.flac
Morphology - Vortex Traks Vol. 02 - 02 32.flac
...
Various Artists - Vortex Traks Vol. 02 - Kan3da_Dancing_Data_by_Framework_Visuals.mov
Various Artists - Vortex Traks Vol. 02 - VortexTraks_label_VTX003.jpg
$ mv cover.jpg '00 cover.jpg'
$ mv Var*jpg '00 vtx003.jpg'
$ mv 'Kan3da - Vortex Traks Vol. 02 - 01 Dancing Data.flac' 'a1 kan3da - dancing data.flac'
$ mv 'Morphology - Vortex Traks Vol. 02 - 02 32.flac' 'a2 morphology - 32.flac'
...
$ mv Var*mov 'z1 kan3da - dancing data (framework visuals).mov'
$ ls
00 cover.jpg
00 vtx003.jpg
a1 kan3da - dancing data.flac
a2 morphology - 32.flac
b1 mr velcro fastener - caffeine sleep.flac
b2 the guide girls - moonglade temal.flac
z1 kan3da - dancing data (framework visuals).mov

The next step is to re-encode any FLAC files in the release. I'll be using flac_reencode (see above) to automate the process:

$ flac_reencode.sh .
flac_reencode.sh: a1 kan3da - dancing data.flac... copying tags...
flac_reencode.sh: a2 morphology - 32.flac... copying tags...
flac_reencode.sh: b1 mr velcro fastener - caffeine sleep.flac... copying tags...
flac_reencode.sh: b2 the guide girls - moonglade temal.flac... copying tags...

Let's examine the tags already present in the first file:

$ tag_audio.sh -p 'a1 kan3da - dancing data.flac'
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh:           artist name: Kan3da
tag_audio.sh:           track title: Dancing Data
tag_audio.sh:           album title: Vortex Traks Vol. 02
tag_audio.sh:                  date: 2016
tag_audio.sh:          album artist: Various Artists
tag_audio.sh:          track number: 1
tag_audio.sh:               comment: Visit https://vortextraks.bandcamp.com
tag_audio.sh: missing genre composer performer bpm initialkey tracktotal discnumber disctotal rgag rgap rgtg rgtp rgrl

Bandcamp and the labels there are usually good about supplying sane tags. Next we'll fill in the missing tags & re-do some existing ones using the tag_audio script:

$ for i in *flac; do tag_audio.sh -k albumartist -v "Various" "$i"; done
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh: albumartist changed to: Various
tag_audio.sh: file: a2 morphology - 32.flac
tag_audio.sh: albumartist changed to: Various
...
$ for i in *flac; do tag_audio.sh -k tracktotal -v "4" "$i"; done
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh: tracktotal changed to: 4
...
$ for i in *flac; do tag_audio.sh -k genre -v "Electro" "$i"; done
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh: genre changed to: Electro
...
$ for i in *flac; do tag_audio.sh -k comment -v "Visit vortextraks.bandcamp.com" "$i"; done
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh: comment changed to: Visit vortextraks.bandcamp.com
...
$ 
$ # this is where we'd edit any other tags, as necessary.
$ # for example, to change the album title:
$ # for i in *flac; do tag_audio.sh -k albumtitle -v "newtitle" "$i"; done
$ 
$ # anyway, let's see what we have now
$ tag_audio.sh -p 'a1 kan3da - dancing data.flac'
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh:           artist name: Kan3da
tag_audio.sh:           track title: Dancing Data
tag_audio.sh:           album title: Vortex Traks Vol. 02
tag_audio.sh:                  date: 2016
tag_audio.sh:                 genre: Electro
tag_audio.sh:          album artist: Various
tag_audio.sh:          track number: 1
tag_audio.sh:          total tracks: 4
tag_audio.sh:               comment: Visit vortextraks.bandcamp.com
tag_audio.sh: missing composer performer bpm initialkey discnumber disctotal rgag rgap rgtg rgtp rgrl

The final steps are to add replaygain tags using tag_rg, add the key tags using tag_key, and then embed a cover image using tag_cover (that last step isn't necessary here; the image supplied and embedded by bandcamp is fine):

$ for i in *flac; do tag_rg.sh -f "$i"; done
$ for i in *flac; do tag_key.sh -f -w "$i"; done
tag_key.sh: key 'Cm', comment: Cm - Visit vortextraks.bandcamp.com
tag_key.sh: key 'Cm', comment: Cm - Visit vortextraks.bandcamp.com
$ 
$ # the command to embed a cover image would look like:
$ # for i in *flac; do tag_cover -c "00 cover.jpg" "$i"; done
$ 
$ # print the tags in the first file one last time
$ tag_audio.sh -p 'a1 kan3da - dancing data.flac'
tag_audio.sh: file: a1 kan3da - dancing data.flac
tag_audio.sh:           artist name: Kan3da
tag_audio.sh:           track title: Dancing Data
tag_audio.sh:           album title: Vortex Traks Vol. 02
tag_audio.sh:                  date: 2016
tag_audio.sh:                 genre: Electro
tag_audio.sh:                   key: Cm
tag_audio.sh:          album artist: Various
tag_audio.sh:          track number: 1
tag_audio.sh:          total tracks: 4
tag_audio.sh:               comment: Cm - Visit vortextraks.bandcamp.com
tag_audio.sh: replaygain_album_gain: -3.32 dB
tag_audio.sh: replaygain_album_peak: 0.99987602
tag_audio.sh: replaygain_track_gain: -3.32 dB
tag_audio.sh: replaygain_track_peak: 0.99987602
tag_audio.sh: replaygain_reference_loudness: 89.0 dB
tag_audio.sh: missing composer performer bpm discnumber disctotal

And that's what I'm looking for. BPM will be tap tempo-ed later; it's added as you'd expect, tag_audio.sh -k bpm -v "value" "file". The other tags listed as 'missing' are used much less often. These files, this directory, this release, is now ready to be moved to its place in the library.

That's a fairly easy example, Vortex Traks and bandcamp supplied good tag data, but the process is the same when there is bad or no pre-existing data.

Closing

This ended up being another labored explanation of something simple, like the previousa entry in this series. I wrote this up to document my process & illustrate that you don't need an automated tagger or a big program like Foobar2000, Rekordbox, or Serato to manage a collection of music files. Some simple shell scripts (and a lot of time) will do.

There are improvements that could be made to these tools, of course. Without thinking on it too hard the first thing I should do is change tag_key so it doesn't require -w to write tags. The scripts should have better error checking. Also I think that the reference flac encoder is capable of re-encoding files in-place, making my script unnecessary. Will have to look into that.

The next and final part in this series will cover my cmus config. I'll try to have that up sometime in the next few months.

Responses

If you've written a response to this post then please let me know the URL:

You can also submit a "comment" webmention by pressing the button below. It may take a day or two for your comment to appear here and a copy of your comment will be stored at commentpara.de.