Discord Rich Presence for Linux media players
Overview • Supported players • Quick start • Configuration • Web players • Development • Troubleshooting
Reads MPRIS metadata over D-Bus → renders Discord Rich Presence → syncs with current media.
Works with VLC, MPV, Rhythmbox, Strawberry, CMUS, MPD, and more. Has a browser bridge for web players (YouTube Music, SoundCloud, etc.) when browser MPRIS is not enough.
Local player → Discord status, no config needed
local player or browser tab
→ MPRIS metadata on D-Bus
→ mprisence
→ Discord Rich Presence
Browser bridge path (optional - see Web players):
supported website
→ browser extension
→ MPRIS bridge (native host)
→ mprisence
→ Discord Rich Presence
- No config required for common local-player setups
- Handlebars templates for title, artist, album, player name, status, duration, IDs, and more
- Per-player and per-site overrides for app ID, icon, activity type, streaming policy, and status text
- Cover art from metadata, local files, Catbox/Litterbox, MusicBrainz, or ImgBB
- Hot reload for most config changes
- Browser bridge for better metadata, cover art, URLs, and controls on web players
Bundled presets in config/config.default.toml. No setup needed - start mprisence and these appear in Discord automatically.
Local players (MPRIS): Audacious, Amberol, Clementine, CMUS, Elisa, Euphonica, Feishin, Fooyin, Gapless, Gelly, Haruna, Harmony Music, Kew, Lollypop, Media Player Classic Qute Theater, MPV, MPD, Musikcube, MusicBee, QMMP, Quod Libet, Quester, Rhythmbox, AmpCast, SMPlayer, Spotify (legacy), Strawberry, Supersonic, VLC.
Web players (browser bridge): YouTube Music, YouTube, SoundCloud, Bandcamp, Tidal, Apple Music, Qobuz, Amazon Music, Deezer, Yandex Music. Add your own under [web_player.*] with match_patterns.
Note
This covers local media players (VLC, MPV, Strawberry, etc.). For web players (YouTube Music, SoundCloud, etc.), see Web players.
yay -S mprisence
# or: yay -S mprisence-bin# without flakes
nix-env -iA nixpkgs.mprisence
# with flakes
nix profile install nixpkgs#mprisenceDownload .deb from GitHub Releases, then:
sudo dpkg -i /path/to/mprisence_*.debcargo install mprisencegit clone https://github.com/lazykern/mprisence.git
cd mprisence
cargo install --path .mprisenceRun in foreground first to verify it picks up your player. Stop with Ctrl+C.
Start media playback, then in another terminal:
mprisence players list
mprisence players list --detailedIf you see your player listed, Discord shows your activity within seconds.
Example:
$ mprisence players list --detailed
Name Identity Bus Name Source
──── ──────── ──────── ──────
VLC vlc_media_player org.mpris.MediaPlayer2.vlc D-Bus
Strawberry strawberry org.mpris.MediaPlayer2.strawberry D-Bus
systemctl --user enable --now mprisence.serviceIf the command above does not work:
mkdir -p ~/.config/systemd/user
curl -o ~/.config/systemd/user/mprisence.service \
https://raw.githubusercontent.com/lazykern/mprisence/main/mprisence.service
systemctl --user daemon-reload
systemctl --user enable --now mprisence.serviceCheck service status:
systemctl --user status mprisence
journalctl --user -u mprisence -fTip
No config file needed for first run. Create one for overrides.
Config path: ~/.config/mprisence/config.toml
Start from example config:
mkdir -p ~/.config/mprisence
curl -o ~/.config/mprisence/config.toml \
https://raw.githubusercontent.com/lazykern/mprisence/main/config/config.example.tomlReference files:
config/config.example.toml- documented exampleconfig/config.default.toml- bundled player and web-player presetssrc/metadata.rs- template variable reference
template.details,template.state,template.large_text,template.small_text[player.*]- overrides for specific local players[activity_type]and[time]- Discord display behavior[cover.provider]- cover-art sources
Player preset keys are stable names. match_patterns selects the MPRIS
sources they apply to. Unscoped patterns match either normalized identity or
canonical bus name; identity: and bus: restrict the target:
[player.vlc]
match_patterns = ["vlc_media_player", "bus:vlc"]
show_icon = trueBundled presets keep separate Discord application IDs and define an explicit
name for the displayed activity and {{{player}}} template value.
Use the name registered for a custom Discord application instead of bundled player names:
[player.default]
app_id = "YOUR_DISCORD_APP_ID"
use_app_name = trueuse_app_name defaults to false.
Restrict discovery with the same selectors, or by resolved preset/site key:
allowed_players = ["player:vlc", "web_player:youtube_music", "bus:*mpdris2*"]Example: show track title in Discord status instead of player name:
[player.default]
status_display_type = "details"status_display_type controls which text Discord shows in your status:
| Mode | Preview |
|---|---|
name - player/app name |
![]() |
state - template.state render (default: artists) |
![]() |
details - template.details render (default: title) |
![]() |
mprisence configWeb-player config options ([web_player.*]) are documented in the Web players section.
To run with local players only, turn website detection off:
web_player_enabled = falseWith this off, xesam:url and title suffixes are not inspected. Browsers
resolve through [player.*] like any other player and [web_player.*] rules
are inert. Because [player.default] has allow_streaming = false, a native
browser needs an explicit player entry to remain visible:
[player.firefox]
match_patterns = ["firefox"]
ignore = false
allow_streaming = trueTo hide one site instead of all websites, set ignore = true on that site's
entry. A website without a matching [web_player.*] entry is always hidden.
Matched web players always allow streaming.
mprisence supports two paths for browser media. Try Browser MPRIS first; switch to the bridge if metadata or controls are lacking.
| Browser MPRIS | Bridge + extension | |
|---|---|---|
| Setup | None | Native host + extension |
| Metadata | Title, maybe artist, URL | Title, artist, album, cover, canonical URL |
| Controls | Play/pause | Full (prev, next, seek) |
| Works with | Any browser with MPRIS support | Bundled sites + presets |
Use this path for richer title, cover art, canonical URL, duration, and controls.
Bundled site support includes:
- YouTube Music, YouTube, SoundCloud, Bandcamp, TIDAL, Apple Music
- Plus presets for Deezer, Qobuz, Amazon Music, Yandex Music, and more
- Firefox: mprisence bridge on AMO
- Chrome / Chromium: mprisence bridge on Chrome Web Store
mprisence web install
mprisence web doctorOpen a supported site (e.g. music.youtube.com) and play a track. Check with playerctl -l | grep mprisence_web.
Development: build and load unpacked
cd extension
npm install
npm run build:firefox # or: npm run build:chromium- Firefox:
about:debugging#/runtime/this-firefox→ Load Temporary Add-on →extension/dist/firefox/manifest.json - Chromium:
chrome://extensions→ Developer mode → Load unpacked →extension/dist/chromium/
Reloading the extension kills content scripts on existing tabs. Refresh media tabs after reload.
playerctl -l | grep mprisence_web
tail -f /tmp/bridge-stderr.logFor full detail: extension/README.md
Some browsers expose media tabs as MPRIS players with page URL metadata. When quality is adequate, mprisence matches these against [web_player.*] presets.
Check what your browser exposes:
playerctl -l
mprisence players list --detailedEnable specific sites via config.
Bundled site (patterns inherited from bundled entry - un-ignore to activate):
[web_player.youtube]
ignore = falseCustom site (not in bundle - provide match_pattern and app_id):
[web_player.my_site]
match_pattern = "mysite.com"
name = "My Site"
app_id = "YOUR_DISCORD_APP_ID"
icon = "https://mysite.com/icon.png"
ignore = falsecargo build --release -p mprisence
./target/release/mprisence web install
cd extension && npm install && npm run build:firefox| Path | Purpose |
|---|---|
src/ |
core daemon: MPRIS discovery, metadata, cover art, config, Discord presence |
src/web_bridge/ |
native host mode for browser sources |
extension/ |
browser extension for supported web players |
config/ |
bundled defaults and example config |
tests/ |
integration and metadata tests |
packaging/ |
packaging scripts and distro assets |
# verbose logging
RUST_LOG=debug mprisence
RUST_LOG=trace mprisence
# validate version string logic
mprisence version validate 1.7.0-beta.3Check:
- Discord desktop client running
- Activity-sharing setting enabled
mprisenceprocess or service running- Player visible in
mprisence players list - Logs show no errors
systemctl --user status mprisence
mprisence players list --detailed
journalctl --user -u mprisence -fPlayer detected, but presence still hidden
Player may be ignored by config or blocked as streaming source.
mprisence config
mprisence players list --detailedAdd matching [player.*] override or adjust [web_player.*] entry.
- Browser MPRIS path: browser may not expose enough metadata
- Bridge path: extension may not be loaded, native host may not be installed, or tab may need refresh after extension reload
Useful checks:
playerctl -l
playerctl -l | grep mprisence_web
./target/release/mprisence web doctor
tail -f /tmp/bridge-stderr.logRUST_LOG=debug mprisence
rm -rf ~/.cache/mprisence/cover_artThen verify provider config and metadata quality.
If you use Vesktop Flatpak, native IPC may need extra setup. See Vesktop guide for native applications: https://github.com/flathub/dev.vencord.Vesktop?tab=readme-ov-file#native-applications
If problem persists, open an issue with:
- player name and
mprisence players list --detailedoutput - relevant config snippet
- logs from
journalctl --user -u mprisence -f - bridge logs if browser path involved


