Skip to main content

mpd2mpris

Build Release License: GPL-3.0-or-later Python MPD APT

mpd2mpris provide MPRIS 2 support to mpd (Music Player Daemon).

Formerly named mpDris2. Renamed to mpd2mpris (in agreement with the original maintainer) to avoid confusion with the original mpDris2, which this project no longer shares code with after the asyncio rewrite.

mpd2mpris runs in the user session and monitors a local or distant mpd server.

Contents

Features

  • Full MPRIS 2 interface (playback control, metadata, seek, volume) for any MPRIS client: playerctl, media keys, desktop applets.
  • Pure asyncio + dbus-fast: single event loop, no threads, no GLib.
  • Local or remote MPD, with automatic reconnect and capability probing.
  • A 7-step cover-art pipeline that resolves artwork for tagged files, CD (CUE/cdda) tracks and web-radio streams (see Cover art).
  • Optional remote cover sources: MusicBrainz/CAA, iTunes, Deezer, Radio Browser, myMPD WebradioDB.
  • systemd user unit with D-Bus activation: starts on the first MPRIS call.
  • Light footprint: only python-mpd2 and dbus-fast at runtime.

Install

From the Odio APT repository:

curl -fsSL https://apt.odio.love/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/odio.gpg
echo "deb [signed-by=/usr/share/keyrings/odio.gpg] https://apt.odio.love stable main" \
    | sudo tee /etc/apt/sources.list.d/odio.list
sudo apt update
sudo apt install mpd2mpris

The shipped systemd user unit is Type=dbus and a matching D-Bus service file is installed, so mpd2mpris auto-starts on the first MPRIS call (playerctl, a media key, a desktop applet, …). Enable it explicitly only if you want it running before any client asks:

systemctl --user enable --now mpd2mpris.service

From PyPI

pipx install mpd2mpris     # or: pip install --user mpd2mpris

This installs the mpd2mpris console script only — no systemd or D-Bus service files, unlike the .deb. To auto-start it, drop a user unit at ~/.config/systemd/user/mpd2mpris.service (copy data/user/mpd2mpris.service) and systemctl --user enable --now mpd2mpris.service. The optional cover deps are pipx install 'mpd2mpris[cover]'.

From git

git clone https://github.com/b0bbywan/mpd2mpris.git
cd mpd2mpris
pipx install .          # or: pip install --user .

This installs the mpd2mpris console script into your $PATH. Start it via a systemctl --user unit.

Tagged releases on GitHub also publish an sdist tarball (mpd2mpris-X.Y.Z.tar.gz) next to the .deb, installable with pipx install ./mpd2mpris-X.Y.Z.tar.gz.

Runtime dependencies: python-mpd2 and dbus-fast. Python 3.11+.

Configuration

By default mpd2mpris connects to localhost:6600. Environment variables $MPD_HOST and $MPD_PORT are honoured. To change anything else, copy the example file shipped at /usr/share/doc/mpd2mpris/mpd2mpris.conf to ~/.config/mpd2mpris/mpd2mpris.conf and edit.

Cover-art resolution needs music_dir to be set (or auto-detected over a local Unix socket connection to MPD). See Cover art below for the full pipeline.

Restart mpd2mpris (pkill -HUP mpd2mpris, or just restart your session) to pick up config changes.

Note: the [Bling] mmkeys option from the historical mpDris2 is no longer supported. Modern desktops (GNOME, KDE, sway with mpris-ctrl, …) read MPRIS directly for multimedia-key handling, so mpd2mpris doesn't need to grab the keys itself anymore.

Sample configuration

[Connection]
# Override host / port (or set $MPD_HOST / $MPD_PORT in the environment).
host = 192.168.1.5
port = 6600
password =

[Library]
# Required for cover-art resolution when MPD is remote (auto-detected
# over a local Unix socket connection).
music_dir = /media/music/
# Override the default cover-file regex; useful for non-standard names.
#cover_regex = ^(album|cover|\.?folder|front).*\.(gif|jpe?g|png|webp|bmp)$

[Cover]
# Remote cover-art sources (pipeline step 5), as an ordered, comma-separated
# list — the order is the lookup priority, and a source not listed is off.
# Valid: musicbrainz, itunes, deezer. Unset = none. MusicBrainz/CAA needs the
# [cover] extra (see below); iTunes/Deezer don't.
#sources = musicbrainz, itunes, deezer
# Web-radio stream cover sources (steps 6-7), same ordered-list rule. Valid:
# radiobrowser (station favicon), mympd (myMPD WebradioDB). Unset = none.
#stream_sources = mympd, radiobrowser
# Base URL of a myMPD instance — the data the 'mympd' stream source needs.
# Listing 'mympd' above without this is a no-op.
#mympd_uri = http://localhost:8080

[Bling]
# CD-like Previous: if elapsed >= 3 s, restart the current track instead
# of jumping to the previous one.
cdprev = False

mpd2mpris does not raise its own desktop notifications: modern desktops (GNOME, KDE, sway with playerctld, …) surface track changes straight from the MPRIS metadata mpd2mpris exports.

Architecture

mpd2mpris is an asyncio + dbus-fast rewrite of the original PyGObject / dbus-python implementation: a single asyncio event loop replaces the GLib MainLoop + thread pool, dbus-fast replaces dbus-python, and mpd.asyncio from python-mpd2 replaces the blocking client.

Development

A top-level Makefile wraps the day-to-day commands so local dev and CI stay in sync (the GitHub workflow calls the same targets):

make lint           # ruff + mypy
make test           # pytest
make build          # python -m build (sdist + wheel)
make deb            # dpkg-buildpackage -b -us -uc (Debian toolchain)
make clean          # drop build/, dist/, *.egg-info
make version        # print the Python version (from __init__.py)
make sync-deb       # bump debian/changelog to match __init__.py

mpd2mpris/__init__.py is the single source of truth for the version; make sync-deb and make check-tag TAG=… keep debian/changelog and the git tag aligned with it.

Build a .deb

Build-deps (per debian/control): debhelper-compat (= 13), dh-python, python3, python3-setuptools. Then make deb on Debian trixie or a derivative produces the .deb. The runtime deps (python3-mpd, python3-dbus-fast) are resolved by APT at install time, not at build time.

Cover art

mpd2mpris resolves mpris:artUrl through a fixed pipeline. The first step that yields a usable image wins; later steps are skipped.

# Step Source Exposed mpris:artUrl Wins when…
1 MPD readpicture Embedded picture in the audio file (FLAC PICTURE, ID3 APIC, …) file:///tmp/cover-*.{jpg,png,…} The track carries embedded art
2 FS regex scan cover_regex match in the song's directory (default matches cover.*, folder.*, album.*, front.*) file:// URI of the matched file (RFC-3986 percent-encoded) A non-standardly-named cover sits next to the audio file (local FS only)
3 MPD albumart cover.{png,jpg,jxl,webp} in the song's directory (resolved server-side by MPD) file:///tmp/cover-*.{jpg,png,…} Remote MPD, or step 2 missed (standard name only)
4 CUE/cdda fallback cover_regex match next to the loaded .cue playlist (FS scan), falling back to MPD albumart (which server-side resolves cover.{png,jpg,jxl,webp}) when music_dir isn't locally accessible file:// URI of the matched file (local FS) or file:///tmp/cover-* (remote MPD) The song is a CUE virtual track (cdda://, http://, …) and the CUE's own directory holds a cover
5 Remote cover URL MusicBrainz/CAA, iTunes, Deezer — whichever are listed in [Cover] sources, in that priority order. For web radio (title only) each source resolves the album within its own catalogue Remote image URL (image not downloaded) Earlier steps failed, a source is enabled and has cover art for the (artist, album)
6 Station favicon Community Radio Browser lookup of the stream URL (radiobrowser in [Cover] stream_sources) Station favicon URL (image not downloaded) An http(s):// web-radio stream whose station has a favicon
7 myMPD WebradioDB MYMPD_API_WEBRADIODB_RADIO_GET_BY_URI against the myMPD at [Cover] mympd_uri (mympd in [Cover] stream_sources) WebradioDB cover URL (image not downloaded) A web-radio stream that the configured myMPD's WebradioDB knows

Step 5's MusicBrainz/CAA lookup needs the optional [cover] extra (pip install '.[cover]', or the python3-musicbrainzngs package); artist/title validation is stdlib (difflib). The iTunes, Deezer and myMPD fallbacks are stdlib-only. Steps 5–7 return a remote URL used as mpris:artUrl — the MPRIS client fetches it, nothing is downloaded or cached to disk.

Used in

  • odio (odios): an open-source, self-hosted multi-protocol audio streamer that turns a Raspberry Pi or Debian box into a hi-fi network receiver. It bundles Bluetooth A2DP, AirPlay, Snapcast multi-room, UPnP/DLNA, Spotify Connect, automatic CD playback and web radio on top of MPD. Odio runs mpd2mpris to expose its MPD over MPRIS2, including the cover pipeline that resolves artwork for CD and web-radio playback.

Contributing

Issues and pull requests are welcome on GitHub.

git clone https://github.com/b0bbywan/mpd2mpris.git
cd mpd2mpris
pip install -e '.[dev,cover]'   # dev tooling + optional cover deps
make lint                       # ruff + mypy
make test                       # pytest

Run make lint and make test before opening a PR, and keep commits focused (one logical change each). Module layout and responsibilities are documented in CLAUDE.md.

Filing a bug? Run the daemon with mpd2mpris -v and paste the verbose log into the issue.

Credits

mpd2mpris (formerly mpDris2) is an asyncio + dbus-fast rewrite of the original mpDris2, whose authors are Erik Karlsson, Jean-Philippe Braun, Christoph Reiter and Mantas Mikulėnas. The Debian packaging traces back to Simon McVittie.

License

mpd2mpris is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). See COPYING for the full text.

Metadata

Release files for mpd2mpris 0.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mpd2mpris 0.13.0
File Size Uploaded
mpd2mpris-0.13.0.tar.gz 88.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mpd2mpris 0.13.0
File Interpreter ABI Platform
mpd2mpris-0.13.0-py3-none-any.whl Python 3 none any Details

Total release size: 148.8 kB

Release files / mpd2mpris-0.13.0.tar.gz

Download URL mpd2mpris-0.13.0.tar.gz
Size 88.4 kB
Tags Source
SHA-256 checksum
How to use checksums
b25bd24860631e46b339ea00e95648ad33c163747572767e14991e32c04102ef
BLAKE2b-256 checksum
How to use checksums
a899e619589ea7d86e4bd43c20fefb11ab040b4e01186bbd6e380a3676f38ca6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Release files / mpd2mpris-0.13.0-py3-none-any.whl

Download URL mpd2mpris-0.13.0-py3-none-any.whl
Size 60.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9cf0a2e0c46a94d12f670272ac025b16024032cbf31486ff31afcf5a8e278404
BLAKE2b-256 checksum
How to use checksums
8198224e13d7531558cd45818a1b963f8fabdfbb436527658e975affbce88cf1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.13.0 This release

2 release files

0.12.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page