complete-computing-environment/beets.org

354 lines
10 KiB
Org Mode
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

:PROPERTIES:
:ID: cce/beets
:ROAM_ALIASES: beets
:END:
#+TITLE: Music Library Management with beets
#+ARCOLOGY_KEY: cce/beets
#+AUTO_TANGLE: t
#+ARROYO_MODULE_WANTS: cce/configure_packaging.org
#+ARCOLOGY_ALLOW_CRAWL: t
I do not like =beets=, but I like everything else less, especially manual [[id:3182614c-9122-4b01-ac3f-9f99e56bfdbd][Music]] metadata management. Because I must, my setup is a bit non-standard, I do some hackery with paths and tags in beets to organize my music so that [[id:cce/syncthing][Syncthing]] can more easily sync important parts to my devices rather than fucking around with generating file-exclusion lists and such.
I install it in [[id:cce/home-manager][home-manager]] with the =copyArtifacts= plugin.
#+begin_src nix :tangle ~/arroyo-nix/hm/beets.nix
{ pkgs, config, ... }:
let
myBeets = with pkgs; beets.override {
pluginOverrides = {
beetcamp = {
propagatedBuildInputs = [ pkgs.beetcamp ];
};
copyartifacts = {
propagatedBuildInputs = [ beetsPackages.copyartifacts ];
};
};
};
in {
home.activation.beets-config =
pkgs.lib.mkActivationLocalLink config
"~/Music/beets/config.yaml"
".config/beets/config.yaml";
# home.packages = [ myBeets ];
home.packages = [ myBeets pkgs.beetcamp ];
}
#+end_src
#+ARROYO_HOME_MODULE: hm/beets.nix
#+ARROYO_SYSTEM_EXCLUDE: droid
* DONE check up on [[https://github.com/NixOS/nixpkgs/pull/172032#issuecomment-1137987507][nixpkgs]] comment about copyartifacts plugin
SCHEDULED: <2022-05-27 Fri>
:LOGBOOK:
- State "DONE" from "NEXT" [2022-06-11 Sat 18:23]
:END:
* INPROGRESS add [[https://github.com/snejus/beetcamp][beetcamp]] to package external plugins
:PROPERTIES:
:ID: 20220611T182415.660603
:ROAM_REFS: https://github.com/NixOS/nixpkgs/pull/176978
:ROAM_ALIASES: beetcamp
:END:
:LOGBOOK:
- Note taken on [2022-06-11 Sat 18:24] \\
https://github.com/NixOS/nixpkgs/pull/176978
- State "INPROGRESS" from "NEXT" [2022-06-11 Sat 18:24]
:END:
#+begin_src nix :tangle ~/arroyo-nix/pkgs/beetcamp.nix
{ lib,
fetchFromGitHub,
python3Packages,
callPackage,
beets,
propagateBeets ? false
}:
python3Packages.buildPythonPackage {
pname = "beets-beetcamp";
version = lib.pkgVersions.beetcamp.version;
src = callPackage lib.pkgVersions.beetcamp.src {};
format = "pyproject";
propagatedBuildInputs = with python3Packages; [ setuptools poetry-core requests cached-property pycountry python-dateutil ordered-set ]
++ (lib.optional propagateBeets [ beets ]);
postInstall = ''
rm $out/lib/python*/site-packages/LICENSE
mkdir -p $out/share/doc/beetcamp
mv $out/lib/python*/site-packages/README.md $out/share/doc/beetcamp/README.md
'';
checkInputs = with python3Packages; [
# pytestCheckHook
pytest-cov
pytest-randomly
pytest-lazy-fixture
rich
tox
types-setuptools
types-requests
] ++ [
beets
];
meta = {
homepage = "https://github.com/snejus/beetcamp";
description = "Bandcamp autotagger plugin for beets.";
license = lib.licenses.gpl2;
inherit (beets.meta) platforms;
maintainers = with lib.maintainers; [ rrix ];
};
}
#+end_src
* File Organization
:PROPERTIES:
:ID: music-file-organization
:ROAM_ALIASES: "Music File Organization"
:END:
I keep my music in =~/Music= and a few subdirectories underneath it so that i can use [[id:cce/syncthing][Syncthing]]'s filtering to narrow the [[id:3182614c-9122-4b01-ac3f-9f99e56bfdbd][Music]] i sync to devices with less storage like the [[id:cosmo_communicator][Cosmo Communicator]] or whatever.
- Albums I download go in to [[file:~/Music/New][New]], usually just unzipped and kept outside of beets.
- [[file:~/Music/High/][High]] contains music I want anywhere
- [[file:~/Music/Middle][Middle]] contains music that is interesting but I do not listen to often
- [[file:~/Music/Low][Low]] is where music I don't listen to or purchased without fully intending to listen to live
- [[file:~/Music/Archive][Archive]] is where music goes to die
- [[file:~/Music/Archive Old][Archive Old]] contains low quality rips and music I listened to when I was much younger.
To import an album in a particular class collection:
#+begin_src shell
~/.nix-profile/bin/beet -c ~/Music/beets/config.yaml import --set=class=high --write --resume $IMPORT_PATH
#+end_src
to modify existing and move them:
#+begin_src shell
~/.nix-profile/bin/beet -c ~/Music/beets/config.yaml modify class=low low:1
#+end_src
** interactive command for importing a zip file or glob of them in to beets from [[id:cce/dired_file_manager][Dired File Manager]]
I hate using =unzip=, such terrible ergonomics. I have this tiny helper shell-script to unzip to =/tmp= and then I wrap it in an interactive command [[elisp:(cce/import-to-beets)]] to make it most easy:
#+ARROYO_EMACS_MODULE: beets
#+begin_src emacs-lisp :tangle beets.el
(defvar beet-command "~/.nix-profile/bin/beet -c ~/Music/beets/config.yaml import --write --resume")
(defun cce/import-to-beets (file class)
"Import a Bandcamp zip FILE in to a CLASS in my Music folder."
(interactive "ffile or directory to import? \nMimport-class? ")
(let ((directory
(if (s-ends-with? "zip" file)
(progn
(shell-command (format "bash ~/org/cce/beets_unzip.sh \"%s\"" (expand-file-name file)) "*beets_unzip*" "*beets_unzip_error*")
(if (and (get-buffer "*beets_unzip_error*") (buffer-size (get-buffer "*beets_unzip_error*")))
(error "zip script failed")
(with-current-buffer (get-buffer "*beets_unzip*")
(buffer-string))))
file)))
(async-shell-command
(format "%s --set=class=%s \"%s\""
beet-command class
directory)
"*beets-import*")))
#+end_src
#+begin_src shell :tangle beets_unzip.sh :shebang #!/bin/env sh
TMPD=$(mktemp -d /tmp/bandcampXXXX)
cd $TMPD
unzip "$1" &>/tmp/bandcamp_unzip.log
echo $TMPD
#+end_src
** NEXT tag out "night music", ambient sleep stuff and code drone, music to sing along
* Beets Configuration
#+begin_src yaml :tangle ~/Music/beets/config.yaml
plugins: fetchart embedart convert scrub replaygain lastgenre web fetchart smartplaylist copyartifacts discogs bandcamp
directory: /home/rrix/Music
library: /home/rrix/Music/beets/musiclibrary.blb
art_filename: albumart
threaded: yes
original_date: no
per_disc_numbering: no
#+end_src
The class field describes the [[id:music-file-organization][file organization hierarchy]] and is used in the path selection per the [[https://beets.readthedocs.io/en/stable/guides/advanced.html#choose-a-path-style-manually-for-some-music]["Advanced Awesomeness"]] documentation to achieve this.
#+begin_src yaml :tangle ~/Music/beets/config.yaml
paths:
default: New/%asciify{$albumartist}/%asciify{$album}%aunique{}/$track - %asciify{$title}
class:high: High/%asciify{$albumartist}/%asciify{$album}%aunique{}/$track - %asciify{$title}
class:middle: Middle/%asciify{$albumartist}/%asciify{$album}%aunique{}/$track - %asciify{$title}
class:low: Low/%asciify{$albumartist}/%asciify{$album}%aunique{}/$track - %asciify{$title}
class:archive: Archive/%asciify{$albumartist}/%asciify{$album}%aunique{}/$track - %asciify{$title}
#+end_src
I use =copyartifacts= to copy album art, pdfs, etc
#+begin_src yaml :tangle ~/Music/beets/config.yaml
copyartifacts:
extensions: .*
#+end_src
import configuration is pretty simple, geared towards assuming the files are fungible, and indeed they are since i'll probably be running imports on my laptop from bandcamp downloads:
#+begin_src yaml :tangle ~/Music/beets/config.yaml
import:
languages: en ja
write: yes
copy: no
move: yes
resume: ask
incremental: yes
quiet_fallback: skip
timid: no
log: /home/rrix/Music/beets/beet.log
#+end_src
I use [[id:20220611T182415.660603][=beetcamp=]]:
#+begin_src yaml :tangle ~/Music/beets/config.yaml
bandcamp:
search_max: 5
art: yes
genre:
capitalize: no
mode: progressive
#+end_src
Fetch genres from Last.FM:
#+begin_src yaml :tangle ~/Music/beets/config.yaml
lastgenre:
auto: yes
source: album
#+end_src
Embed album art in the files
#+begin_src yaml :tangle ~/Music/beets/config.yaml
embedart:
auto: yes
remove_art_file: yes
#+end_src
Fetch art where possible
#+begin_src yaml :tangle ~/Music/beets/config.yaml
fetchart:
auto: yes
sources: "*"
store_source: yes
#+end_src
Enable and disable various other plugins:
#+begin_src yaml :tangle ~/Music/beets/config.yaml
chrome:
auto: yes
replaygain:
auto: no
scrub:
auto: yes
replace:
'^\.': _
'[\x00-\x1f]': _
'[<>:"\?\*\|]': _
'[\xE8-\xEB]': e
'[\xEC-\xEF]': i
'[\xE2-\xE6]': a
'[\xF2-\xF6]': o
'[\xF8]': o
'\.$': _
'\s+$': ''
web:
host: 0.0.0.0
port: 8337
reverse_proxy: true
acousticbrainz:
auto: yes
#+end_src
** Smart Playlists
run [[shell:beet -c ~/Music/beets/config.yaml splupdate &]] (make sure to tangle this if you change it!):
#+begin_src yaml :tangle ~/Music/beets/config.yaml
smartplaylist:
relative_to: /home/rrix/Music
playlist_dir: /home/rrix/Music/playlists
playlists:
- name: upbeat.m3u
query:
- mood_happy::^0.99 ^genre::Rock ^artist::Vanilla ^artist:Bananarama ^album::Evangelion ^album::3.0 ^genre:Grunge ^class:archive
- artist:"Electric Six"
- danceable::^0.99999 ^genre::Rock ^artist::Vanilla ^artist:Bananarama ^album::Evangelion ^album::3.0 ^genre:Grunge ^class:archive
- name: chiptunes.m3u
query:
- artist:Anamanaguchi
- artist:"Bit Shifter"
- artist:Chipzel
- artist:chipzel
- artist::Demoscene
- album::Fez
- album::"Hyper Light Drifter"
- album::"Toffelskater"
- artist:Fantomenk
- artist:"Fighter X"
- artist:"PDF Format"
- artist:Sabrepulse
- artist:Spamtron
- artist:spamtron
- genre:8-bit
- genre:Chiptunes
- name: j-pop.m3u
query:
- album::[Gg][Uu][Nn][Dd][Aa][Mm]
- album::ガンダムユニコ
- artist::まりや
- artist:"Maria Asahina"
- artist:"松原みき"
- album::NieR
- genre:J-pop
- genre:J-Rock
- name: various-and-sundry.m3u
query:
- album:"Birdy Nam Nam"
- artist::Flashbulb
- genre:vaporwave
- genre:Ambient
- artist:'Janel & Anthony'
- artist:'Anthony Pirog'
- name: music-for-sleep.m3u
query:
- album:CATCHWave
- album::Disassembly
- artist:"Music For Sleep"
- album:"Glider 10"
- album:Liminal
- album:"Solar Fields"
- artist:"Matt Borghi"
- artist:"Umber"
- artist:"the volume settings folder"
- artist:"Brian Eno"
#+end_src