Music with MPD and beets
MPD and beets
- author
-
akeil
- date
-
2014-03-24
- version
-
1
MPD 5 (Music Player Daemon) is a music player that runs in the background (as a daemon process). MPD does not have a user interface but requires a separate client application to control playback. One interesting thing about MPD is that it can be controlled over the network. MPD can also stream music over HTTP.
beets 1 is a command line application to manage a music library. It downloads album/track-information and cover art from various web services and manages your music-file's metadata ("tags").
The resulting setup will be a system where you can playback and manage music without the need for a graphical user interface (or any graphics). It can run on your desktop PC and be controlled by a locally installed (GUI-) client or it can run on a different machine and be controlled over the network. When controlled via network, no display is required on the computer running thee beets/MPD combo.
Install beets
The installation procedure is also described in the beets documentation 2.
Install Manually
beets can also be installed manually inside a virtualenv 4. This allows to install it without root privileges (for a single user only) and also keeps the system-wide python installation clean. However, when installed like this, one must update it manually..
Install python-virtualenv
if it is not already installed.
beets will run with Python 2.7 only, so install that version
of Python as well.
On Ubuntu:
# apt-get install python2.7 python2.7-dev python-virtualenv
On Arch Linux
# pacman -S python2 python2-virtualenv
Next, create a virtualenv and install beets:
$ mkdir ~/.virtualenvs $ cd ~/.virtualenvs $ virtualenv --python python2.7 beets $ source beets/bin/activate (beets)$ pip install beets
Now beets can be executed with the beet
command - as long as
you have the beets virtualenv activated.
To execute outside the virtualenv, link the beet
executable
into ~/bin
(assuming that ~/bin
is in your $PATH
):
$ ln -s ~/.virtualenvs/beets/bin/beet ~/bin/beet
Updating the virtualenv-install is done like this:
$ source ~/.virtualenvs/beets/bin/activate (beets)$ pip install --upgrade beets
Plugins
Beets offers several plugins. For some of them, additional packages must be installed.
Some interesting of the many beets plugins 3:
- discogs
-
Use discogs 7 as an additional source for metadata (default is musicbrainz 6).
- lyrics
-
Fetches song lyrics.
- echonest
- fetchart
-
Fetches cover art. Requires ImageMagick or PIL to re-size downloaded art.
- embedart
-
Embeds cover art into the music file. Also requires ImageMagick 8 or PIL 9 to re-size images.
- lastgenre
-
Fetches genre from last.fm 10 and optionally reduces genres to a canonized list.
- replaygain
-
Calculates Replay Gain, using either
mp3gain
orreplaygain
. - scrub
-
Removes unwanted tags from music files.
- mbsync
-
Updates your library with new metadata from MusicBrainz.
- missing
-
Finds missing tracks in your collection.
- duplicates
-
Finds and optionally deletes duplicate albums/tracks.
Plugin requirements:
Plugin |
Requirement |
Install with |
---|---|---|
discogs |
discogs-client |
pip |
echonest_tempo |
pyechonest |
pip |
lastgenre |
pylast |
pip |
mpdstats |
python-mpd |
pip |
fetchart |
imagemagick |
(package manager) |
replaygain |
mp3gain replaygain |
(package manager) |
To install the python requirements (assuming that beets was installed in a virtualenv):
(beets)$ pip install discogs-client pyechonest pylast python-mpd
To install the additional packages required by beets or plugins:
# apt-get install mp3gain replaygain imagemagick
A simple update script for the complete beets virtualenv:
#!/bin/sh VENV="$HOME/.virtualenvs/beets" $VENV/bin/pip install --upgrade beets discogs-client pyechonest pylast
Configure
The beets config file is ~/.config/beets/config.yaml
.
The beets config is always user-based (this cannot be changed -
however, since version 1.3.3, an additional configuration file can
be supplied via the --config
option).
Change the base directory where beets stores music files:
directory: /mnt/storage/music/
A complete list of beets configuration options 12 can be found in the beets documentation:
The default config from the installation directory can be used a a starting point for a personal config.
$ cp ~/.virtualenvs/beets/lib/python2.7/site-packages/beets/config_default.yaml \ ~/.config/beets/config.yaml
Import Settings
Files to be imported will be placed in a special "import" folder, which is intended to contain to-be-imported files only. beets should clean up this directory after import. Settings are:
import: move: yes
Use the strong_rec_thresh setting to allow more or less imperfectly matched albums to be imported without prompt:
strong_rec_thresh: 0.1 # match 90% or better for auto-import
Genres
The lastgenre plugin will fetch genres from last.fm Additionally, the last.fm genre is compared against a whitelist, to exclude some of the genres. It is also possible to canonicalize the genres to a more coarser set of genres using a YAML-configuration file.
For both options, default files are included at:
~/.virtualenvs/beets/lib/python2.7/site-packages/beetsplug/lastgenre/genres.txt ~/.virtualenvs/beets/lib/python2.7/site-packages/beetsplug/lastgenre/genres-tree.yaml
Copy these to ~/.config/beets/
and configure
beets to use these files. Edit the files as required.
lastgenre: whitelist: ~/.config/beets/genres.txt canonical: ~/.config/beets/genres-tree.yaml
MPD
Configure
The system wide config file for MPD is /etc/mpd.conf
relevant settings:
port "6600" music_directory "/var/lib/mpd/music" playlist_directory "/var/lib/mpd/playlists" db_file "/var/lib/mpd/mpd.db" state_file "/var/lib/mpd/state" sticker_file "/var/lib/mpd/sticker.sql" log_file "/var/log/mpd.log" pid_file "/run/mpd/mpd.pid" user "mpd" replaygain "album" metadata_to_use "artist,album,title,track,name,genre,date,disc,albumartist"
To ensure that MPD runs smoothly, create the required files
and chown
them to the mpd-user.
# mkdir -p /var/lib/mpd/playlists # touch /var/lib/mpd/{mpd.db,state,sticker.sql} # chown -R mpd:mpd /var/lib/mpd # touch /var/log/mpd.log # chown mpd:mpd /var/log/mpd.log # mkdir /run/mpd # chown mpd:mpd /run/mpd # ln -s /mnt/storage/music /var/lib/mpd
The music_directory is the only directory defined in the config
that is not created during setup.
Instead we want MPD to use the same directory as beets and symlink
the music directory for MPD.
Make sure that the mpd
user has read permissions on all files
as well as read+execute permissions on all directories
within the music directory.
Port 6600 is the default for MPD. If possible, leave this unchanged as most clients will expect MPD to listen at this port.
user (and group) control the permissions under which MPD is run. On some systems, MPD must be a member of the audio group in order to use the sound card.
The var/lib/mpd
directory should look as follows:
$ ls -l /var/lib/mpd/ total 4 -rw-r--r-- 1 mpd mpd 0 Nov 23 18:32 mpd.db lrwxrwxrwx 1 root root 20 Nov 23 18:35 music -> /mnt/storage/music drwxr-xr-x 2 mpd mpd 4096 Nov 17 19:26 playlists -rw-r--r-- 1 mpd mpd 0 Nov 23 18:32 state -rw-r--r-- 1 mpd mpd 0 Nov 23 18:32 sticker.sql
There is an extensive article in the Arch wiki on setting up MPD 13.
Metadata
This config-setting:
metadata_to_use "artist,album,title,track,name,genre,date,disc,albumartist"
tells MPD which tags to include in its database.
You can select tracks by any of these tags.
The albumartist
is not enabled by default.
If the metadata_to_use
setting is changed later, MPD must
rebuild its database for the change to take effect.
MPD will rebuild the database if you delete (or rename) the existing one.
The database is a plain text file; have a look at it.
Stream over HTTP
MPD version 0.15 or up has built in HTTP-streaming.
To enable it, add the following to /etc/mpd.conf
:
audio_output { type "httpd" name "HTTP Stream" encoder "vorbis" port "8000" quality "7.0" #bitrate "128" format "44100:16:2" }
quality
settings for for variable bitrate (VBR) range from
-1 (poor) to 10 (high).
Alternatively, specify a constant bitrate
, e.g. "128".
format 44100:16:2
means 44100khz 16 Bit Stereo
The URL for MPD's stream is then http://192.168.1.2:8000 (if 192.168.1.2 is the IP-address of the machine MPD is running on). For example:
$ mplayer http://192.168.1.2:8000
will have mplayer
start playing whatever MPD currently plays.
MPD Clients
- mpc 17
-
a minimalist command line client. Good for testing or quick commands.
- Ario 14
-
A desktop client with a GUI.
- GMPC 16
-
The Gnome Music Player Client is another GUI client.
- mpDris2 15
-
Adapts the dbus MPRIS interface for MPD. This makes MPD to occur in (and be controlled from) the sound menu of your desktop environment like "normal" music players.
- MPDroid 19
-
MPD client for Android.
MPDroid has a setting to list tracks by Albumartist instead of (Track-)Artist. The
albumartist
must be included in MPD's config asmetadata_to_use
or this setting will not work.
The MPD wiki has a large list of MPD clients 18.
Misc
Automatically Update Metadata
beets
metadata is based primarily on MusicBrainz 6,
which is permanently updated.
To periodically and automatically sync your music collection,
run a script like this (e.g. weekly via cron
):
#!/bin/bash $VENV=/home/username/.virtualenvs/beets # sync metadata $VENV/bin/beet mbsync > /dev/null # fetch coverart $VENV/bin/beet fetchart > /dev/null
Albumart for MPDroid
MPDroid can display the cover of the currently playing song. The cover is not provided by MPD but instead
provided by a web server, running on the same machine as MPD (see MPDroid wiki 20)
Set up a web server like this
# pacman -S nginx # systemctl enable nginx
# apt-get install nginx
The relevant nginx-configuration is this:
http { server{ listen 80; root /mnt/storage/music; location /cover-art/ { rewrite /cover-art/(.*) /$1 break; try_files $uri $uri allow 192.168.1.0/24 # local network deny all # everybody else } } }
Sample Beets Configuration
Complete sample configuration for beets:
# Beets configuration -------------------------------------------------------- directory: /mnt/storage-1/music import: # write metadata to music files write: yes # move imported files from source to the music directory move: yes copy: no delete: no # use auto-tagging where possible # do not require confirmation on strong matches autotag: yes timid: no resume: ask incremental: no none_rec_action: ask log: quiet: no # enable with command line option quiet_fallback: skip default_action: apply singletons: no languages: [] detail: no flat: no # use the release-date of the original (first) release of an album? original_date: no # on multi-disk releases, assign track numbers for the whole album. # If "per disk", make sure tracknames do not collide ("paths" setting). per_disc_numbering: no # files matching these patterns are deleted from source after import clutter: ["Thumbs.DB", ".DS_Store", "*.m3u", ".pls", "*.jpg"] # files/directories matching one of these patterns are ignored during import ignore: [".*", "*~", "System Volume Information"] # Paths ---------------------------------------------------------------------- # Paths and filenames for music files # relative to music directory paths: default: %asciify{$albumartist}/%asciify{$album}%aunique{}/$track %asciify{$title} singleton: Non-Album/%asciify{$artist}/%asciify{$title} comp: Compilations/%asciify{$album}%aunique{}/$track %asciify{$title} # replace special characters in generated filenames replace: '[\\/]': _ '^\.': _ '[\x00-\x1f]': _ '[<>:"\?\*\|]': _ '\.$': _ '\s+$': '' path_sep_replace: _ # filename for the album art art_filename: cover # results in "cover.jpg" max_filename_length: 0 # unlimited # General -------------------------------------------------------------------- # use mutliple threads during import threaded: yes timeout: 5.0 verbose: no # User Interface ------------------------------------------------------------- color: yes list_format_item: %upper{$artist} - $album - $track. $title list_format_album: %upper{$albumartist} - $album time_format: '%Y-%m-%d %H:%M:%S' terminal_encoding: utf8 ui: terminal_width: 80 length_diff_thresh: 10.0 # Auto Tagger ---------------------------------------------------------------- match: strong_rec_thresh: 0.1 # match 90% or better for auto import medium_rec_thresh: 0.25 rec_gap_thresh: 0.25 max_rec: missing_tracks: medium unmatched_tracks: medium distance_weights: source: 2.0 artist: 3.0 album: 3.0 media: 1.0 mediums: 1.0 year: 1.0 country: 0.5 label: 0.5 catalognum: 0.5 albumdisambig: 0.5 album_id: 5.0 tracks: 2.0 missing_tracks: 0.9 unmatched_tracks: 0.6 track_title: 3.0 track_artist: 2.0 track_index: 1.0 track_length: 2.0 track_id: 5.0 preferred: countries: [] media: [] original_year: no ignored: [] track_length_grace: 10 track_length_max: 30 # Plugins -------------------------------------------------------------------- plugins: [ discogs, lyrics, echonest_tempo, fetchart, embedart, lastgenre, scrub, mbsync, mpdupdate, #mpdstats, missing, duplicates ] pluginpath: [] # Plugins Config ------------------------------------------------------------- lyrics: auto: yes fallback: '' echonest_tempo: auto: yes lastgenre: whitelist: ~/.config/beets/genres.txt canoncical: ~/.config/beets/genres-tree.yaml fallback: '' source: artist fetchart: auto: yes maxwidth: 300 cautious: true cover_names: cover folder embedart: auto: yes maxwidth: 300 replaygain: auto: yes overwrite: yes albumgain: yes scrub: auto: yes # required for mpdstats mpd: host: localhost port: 6600 password: # none mpdstats: rating: False # two ratings are calculated: # "rolling" based on recent development # "stable" based on all-time development # rating mix 0.0 is all "rolling", 1.0 is all "stable" rating_mix: 0.75 missing: format: $albumartist - $album - $track - $title count: no total: no duplicates: checksum: no # expensive