{ pkgs, config, ... }: { programs.beets = { enable = true; package = pkgs.beets.override { pluginOverrides = { beatport.enable = true; }; }; settings = { library = "${config.xdg.dataHome}/beets/library.db"; art_filename = "cover"; directory = "${config.xdg.userDirs.music}/beets"; ui = { color = true; }; import = { # move, instead of copying or linking the files copy = false; move = true; link = false; # Show more detail, when beet needs to ask for something detail = true; incremental = false; # Write the metadata to the files write = true; log = "${config.xdg.dataHome}/beets/beetslog.txt"; }; paths = { default = "$genre/$albumartist/$album/$track $title"; singleton = "$genre/$artist/$title"; comp = "$genre/$album/$track $title"; "albumtype:soundtrack" = "Soundtracks/$genre/$album/$track $title"; }; # Plugin config lastgenre = { prefer_specific = false; # Lookup the track, not the album source = "track"; }; fetchart = {}; lyrics = { # Always fetch lyrics (and update them, if some were found) force = true; }; hook = { hooks = [ { # Also generate the replaygain for the album variant (so selecting between # track and album becomes possible) event = "import"; command = "beet replaygain --album"; } ]; }; replaygain = { auto = true; backend = "ffmpeg"; r128_targetlevel = 89; # Re-calculate the replay gain value even for files, that already have one set. overwrite = true; }; duplicates = { keys = ["acoustid_fingerprint"]; }; fuzzy = { # The prefix denoting that a search should be run in fuzzy mode prefix = "."; }; ihate = { warn = [ "title:commentary" ]; }; smartplaylist = { relative_to = config.services.mpd.musicDirectory; playlist_dir = config.services.mpd.playlistDirectory; forward_slash = false; # Show the real m3u file paths, when running `--pretend` pretend_paths = true; playlists = [ { name = "artists/$albumartist.m3u"; query = ""; } ]; }; # scrub = { # auto = true; # }; plugins = [ # Remove all previous tags before import (this is useful to ensure, that # the metadata in the libary.db is synced with the tags on disk) # # FIXME: I think, that this also removes the deezer id, which is not ideal # <2024-08-07> # "scrub" # Calculate replay gain "replaygain" # Show tags on files/queries "info" # Create playlist from `play_count`/`skip_count` (gathered by the `mpdstats` # plugin) # Note that this should come _before_ the `mpdupdate` plugin, to ensure that # `mpdupgate` can propagate changed playlist to `mpd`. "smartplaylist" # Warn, when importing a matching item "ihate" # Allow fuzzy searching "fuzzy" # Put featured artist in the title (this helps with grouping by artist) "ftintitle" # Filter out duplicates "duplicates" # Generate fingerprints "chroma" # Download album art "fetchart" # Fetches tags from `last.fm` and adds them as genres to imported music "lastgenre" # Run commands on events "hook" # Fetch lyrics "lyrics" # Allow beets to understand deezer id's "deezer" "mpdstats" # Transfer MPD stats to beets "mpdupdate" # Update MPD database on import ]; musicbrainz = { # Search for deezer id's and use them in the autotagger external_ids = { deezer = true; }; }; # Log-on config # TODO: Add this, to upload the generated fingerprints (to help improve their # database) <2024-08-07> # acoustid = { # apikey = "TODO"; # }; }; mpdIntegration = { enableStats = true; enableUpdate = true; host = config.home.sessionVariables.MPD_HOST; }; }; }