Skip to content

lazykern/mprisence

Repository files navigation

mprisence

AUR version Nixpkgs

Highly customizable Discord Rich Presence client for MPRIS media players. Supports VLC, MPV, RhythmBox, and many other Linux music and media players.

(Note: Actual appearance depends on your configuration and the specific media player)

Preconfigured Players

Ready to use with popular media players (configured in config.default.toml):

  • Media Players: VLC, MPV, Audacious, Elisa, Lollypop, Rhythmbox, CMUS, MPD, Musikcube, Clementine, Strawberry, Amberol, SMPlayer, Supersonic, Feishin, kew, Quod Libet, Euphonica
  • Streaming: YouTube Music, Spotify (disabled by default)
  • Browsers (disabled by default): Firefox, Zen, Chrome, Edge, Brave

Note: MPD frontends (e.g., Euphonica) will also show MPD rich presence in Discord; you can disable the MPD entry in your config (see Configuration Reference

Feel free to create a new issue if you want your player name+icon to be recognized by mprisence!

Features

  • Works with any MPRIS player (VLC, MPV, Rhythmbox, etc.)
  • Template-driven presence (Handlebars): full control over details/state text, with helpers + conditionals
  • Custom status display: choose what Discord shows as your status (name, state, or details) — globally or per player
  • Cover art: uses metadata, local files, and online providers (with caching)
  • Hot reload: most config edits apply instantly (no restart)
  • Smart activity type: “Listening” / “Watching” / etc. based on content (configurable)
  • Per-player overrides: app IDs, icons, status, and more
  • Rich metadata: access detailed fields (including technical audio info) inside templates

Prerequisites

  • For running: A desktop environment with an active D-Bus session (standard on most Linux desktops).
  • For service management: systemd (user instance).
  • For manual installation/building from source:
    • rustc and cargo (latest stable version recommended)
    • git (to clone the repository)

Installation and Setup

Expand installation and setup steps

Package Manager

Arch Linux

# Install the stable version
yay -S mprisence

# Or, install the latest development version
yay -S mprisence-git

# Or without building from source
yay -S mprisence-bin

Nix (NixOS, Linux)

Available in nixpkgs

# without flakes:
nix-env -iA nixpkgs.mprisence

# with flakes:
nix profile install nixpkgs#mprisence

NixOS configuration:

environment.systemPackages = [ pkgs.mprisence ];

Debian, Ubuntu, and derivatives

Download the .deb package from the GitHub Releases page and install it:

sudo dpkg -i /path/to/mprisence_*.deb

Manual Installation

This method is for other Linux distributions, or if you prefer to install from source or crates.io. It requires a few manual setup steps.

Step 1: Install the mprisence binary

Choose one of the following ways to get the executable:

Option A: From Crates.io (requires Rust)
cargo install mprisence

This will install the binary to ~/.cargo/bin/. Ensure this directory is in your $PATH.

Option B: From GitHub Releases (pre-compiled)

Download the ...-unknown-linux-gnu.tar.gz archive from the GitHub Releases page. Extract it, and place the mprisence binary in a directory included in your system's $PATH (e.g., ~/.local/bin or /usr/local/bin).

Option C: From Source (for development)
# Clone the repository
git clone https://github.com/lazykern/mprisence.git
cd mprisence

# Install from local source
cargo install --path .

This also installs the binary to ~/.cargo/bin/.

Step 2: Set up Configuration

mprisence looks for its configuration at ~/.config/mprisence/config.toml.

  1. Create the configuration directory:

    mkdir -p ~/.config/mprisence
  2. Download the example configuration:

    curl -o ~/.config/mprisence/config.toml https://raw.githubusercontent.com/lazykern/mprisence/main/config/config.example.toml

    Now you can edit this file to customize mprisence. See the Configuration Reference section for more details.

Step 3: Set up and Run the Service

To have mprisence start automatically on login, set up the systemd user service.

  1. Create the systemd user directory if it doesn't exist:

    mkdir -p ~/.config/systemd/user
  2. Download the service file: The provided service file is configured to find the mprisence binary in ~/.cargo/bin/.

    curl -o ~/.config/systemd/user/mprisence.service https://raw.githubusercontent.com/lazykern/mprisence/main/mprisence.service

    Note: If you placed the binary in a different location (e.g., /usr/local/bin), you must edit ~/.config/systemd/user/mprisence.service and change the ExecStart path.

  3. Enable and start the service:

    systemctl --user enable --now mprisence

    This command enables mprisence to start at login and starts it immediately.

Managing the Service

Once the service is installed (either manually or via a package), you can manage it using systemctl --user:

# Check service status
systemctl --user status mprisence

# Restart the service after changing the config
systemctl --user restart mprisence

# View detailed logs
journalctl --user -u mprisence -f

# Stop and disable the service
systemctl --user disable --now mprisence

Configuration

mprisence is highly configurable via ~/.config/mprisence/config.toml (or $XDG_CONFIG_HOME/mprisence/config.toml).

After following the installation steps, you can modify ~/.config/mprisence/config.toml to your liking. The application will hot-reload most configuration changes automatically.

Local Album Covers

mprisence will first attempt to find cover art from MusicBrainz. If it's not found, it can re-host local cover art through Catbox (no key required) or ImgBB (requires an API key).

Update the provider order to include whichever host you prefer (e.g., ["musicbrainz", "catbox", "imgbb"], ["catbox"], etc.).

Catbox (no key required)

[cover.provider]
provider = ["catbox"]

[cover.provider.catbox]
# user_hash = "your_user_hash" # optional: lets you delete uploads later
use_litter = false            # true -> upload to Litterbox instead of permanent Catbox storage
litter_hours = 24             # valid values: 1, 12, 24, 72

ImgBB (API key required)

[cover.provider]
provider = ["imgbb"]

[cover.provider.imgbb]
api_key = "YOUR_API_KEY_HERE"

Notes:

  • Clear cache: rm -rf ~/.cache/mprisence/cover_art.
  • Authenticated/self-hosted art URLs from players like Feishin (Subsonic/OpenSubsonic/Navidrome/Jellyfin API image routes) are treated as source input and re-hosted via your configured providers instead of being cached as direct Discord URLs.

Custom Status Display

Use status_display_type to control which text Discord shows in your status.

status_display_type Preview
name: shows the player/app name in your status Status display type name
state: shows the rendered template.state value (default template shows artist(s)) Status display type state
details: shows the rendered template.details value (default template shows title) Status display type details

Set a global default in [player.default], then override per player only when needed.

# Global default for all players
[player.default]
status_display_type = "name" # name | state | details

# Optional per-player override (this one only affects VLC)
[player.vlc_media_player]
status_display_type = "details"

Configuration Reference


Basic Configuration Example
# Basic settings
# Whether to clear Discord activity when media is paused
clear_on_pause = true

# How often to update Discord presence (in milliseconds)
interval = 2000

# Restrict discovery to specific players (identities, wildcards, or regex).
# Matches against player identity or the bus-name "player" part (e.g., "vlc"),
# not the full D-Bus name. Leave empty to allow all players.
allowed_players = []

# Note: Triple braces `{{{variable}}}` are used to prevent HTML escaping,
# which is generally desired for Discord presence fields.
# See: https://handlebarsjs.com/guide/#html-escaping
# Extra helpers: `eq`, `contains`, `icontains`, `regex_is_match`, and `regex_captures`

# Display template
[template]
# First line in Discord presence
details = "{{{title}}}"

# Second line in Discord presence - using Handlebars array iteration
state = "{{#each artists}}{{this}}{{#unless @last}} & {{/unless}}{{/each}}"
# or just use
# state = "{{{artist_display}}}"

# Text shown when hovering over the large image - using conditional helpers
large_text = "{{#if album}}{{{album}}}{{#if year}} ({{{year}}}){{/if}}{{/if}}"

# Text shown when hovering over the small image (player icon)
# Only visible when show_icon = true in player settings
small_text = "{{#if player}}{{{player}}}{{else}}MPRIS{{/if}}"

# Match substrings or regex patterns in helpers
# details = "{{#if (contains player \"Spotify\")}}{{{title}}}{{else}}{{{player}}}{{/if}}"
# details = "{{#if (icontains player \"spotify\")}}{{{title}}}{{else}}{{{player}}}{{/if}}"
# small_text = "{{#if (regex_is_match pattern=\"^(mpv|vlc)$\" on=player_bus_name)}}Video{{else}}Audio{{/if}}"

# Activity type settings
[activity_type]
# Auto-detect type (audio -> "listening", video -> "watching")
use_content_type = true
# Default type: "listening", "watching", "playing", or "competing"
default = "listening"

# Time display settings
[time]
# Show progress bar/time in Discord
show = true
# true = show elapsed time, false = show remaining time
as_elapsed = true

Cover Art Setup
[cover]
# File names (without extension) to search for local art (e.g., cover.jpg, folder.png)
file_names = ["cover", "folder", "front", "album", "art"]
# How many parent directories to search upwards for local art (0 = same dir only)
local_search_depth = 2

[cover.provider]
# Cover art providers in order of preference
# (catbox will be used as a fallback if musicbrainz fails or local art isn't found)
provider = ["musicbrainz", "catbox"] # Also checks local files first based on above

[cover.provider.musicbrainz]
# Minimum score (0-100) for MusicBrainz matches. Higher = stricter.
min_score = 100

[cover.provider.catbox]
# user_hash = "your_user_hash" # optional: lets you delete uploads later
use_litter = false            # true -> upload to Litterbox instead of permanent Catbox storage
litter_hours = 24             # valid values: 1, 12, 24, 72

[cover.provider.imgbb]
# Your ImgBB API key (get one at: https://api.imgbb.com/)
api_key = "YOUR_API_KEY_HERE"
# How long to keep uploaded images (in seconds, default: 1 day)
expiration = 86400

Player-Specific Configuration
# Use 'mprisence players list' to get the correct player identity (e.g., vlc_media_player)

# Default settings applied to ALL players unless overridden below
[player.default]
ignore = false # Set to true to disable presence for all players by default
app_id = "1121632048155742288" # Default Discord Application ID
icon = "https://raw.githubusercontent.com/lazykern/mprisence/main/assets/icon.png" # Default icon URL
show_icon = false # Show player icon as small image by default?
allow_streaming = false # Allow HTTP/HTTPS streaming content? False clears Discord activity for those players.
status_display_type = "name" # Controls which text Discord shows in your status.
                              # For example:
                              # "name"    -> Player/app name
                              # "state"   -> Rendered template.state value (default: "{{{artists}}}")
                              # "details" -> Rendered template.details value (default: "{{{title}}}")

# Override settings for a specific player (VLC in this example)
[player.vlc_media_player]
# You can override any key from [player.default] here
app_id = "YOUR_VLC_APP_ID_HERE" # Use a VLC-specific Discord App ID
icon = "https://example.com/vlc-icon.png" # Use a VLC-specific icon
show_icon = true # Show the VLC icon
allow_streaming = true # Allow streaming content for VLC
# You could also add 'override_activity_type = "watching"' here if desired
status_display_type = "details"

# Example: Ignore Spotify
# [player.spotify]
# ignore = true

# Example: Wildcard matches
[player."*youtube_music*"]
show_icon = true
allow_streaming = true

When allow_streaming is false, mprisence will skip HTTP/HTTPS sources for that player and clear any previously published Discord activity so browsers stay hidden unless explicitly enabled.

Player config priority: user entries always override bundled ones. The resolver tries user exact > user regex > user wildcard > bundled exact > bundled regex > bundled wildcard; any field left unset on a higher-priority match is filled from the next match down, falling back to [player.default] (user, then bundled) and finally built-in defaults. When identity and bus-name differ (for example with proxies like playerctld), an exact user bus-name entry wins over identity-derived matches.

CLI Commands

# Get help
mprisence --help

# Run without system service
mprisence

# List available MPRIS players
mprisence players list

# Show detailed player information including metadata and config
mprisence players list --detailed

# Show current configuration
mprisence config

# Show version
mprisence version

# Enable more verbose logging
RUST_LOG=debug mprisence # or RUST_LOG=trace mprisence

Troubleshooting

Expand troubleshooting tips

Common Issues

  1. Discord Presence Not Showing / Updating

    • Is your player running and MPRIS-compatible? Run mprisence players list to see detectable players.
    • Is the service running? systemctl --user status mprisence
    • Discord Settings: Check Discord Settings -> Registered Games / Activity Privacy. Ensure Display current activity as a status message. is ON. Sometimes toggling this off and on helps. Add mprisence if it's not listed.
    • Correct App ID? Verify the app_id in your config matches a valid Discord application ID.
    • Using Vesktop Flatpak? Set up the Discord IPC symlink as described in the Vesktop Flatpak guide: Native applications.
    • Logs: Check journalctl --user -u mprisence -f or run RUST_LOG=debug mprisence for errors.
  2. Cover Art Not Displaying

    • Check the logs: Run with RUST_LOG=debug mprisence to see the cover art process.
    • Provider Order: Cover art is checked in this order: Cache -> Direct URL (from metadata) -> Local Files -> Configured Providers (e.g., MusicBrainz, ImgBB).
    • MusicBrainz: Does the track metadata (title, artist, album) accurately match the MusicBrainz database? Check the min_score in your config.
    • ImgBB:
      • Is a local file available (embedded or matching file_names in the folder/parent folders)? ImgBB is primarily used to upload local art.
      • Is your api_key in [cover.provider.imgbb] correct and valid?
      • Is the image file format supported and readable?
    • Cache: Try clearing the cache (rm -rf ~/.cache/mprisence/cover_art) if you suspect stale entries.
  3. Service Issues

    • Use the commands mentioned in the Autostarting / Service Management section to check status (status), view logs (journalctl), and manage the service (start, stop, restart).
  4. Configuration Issues _Syntax Errors: Validate your config.toml using an online TOML validator or toml-lint. _ Defaults: If unsure, temporarily remove your ~/.config/mprisence/config.toml to test with the built-in defaults.

Contributing

Contributions are welcome! Please feel free to open an issue to report bugs, suggest features, or discuss changes. If you'd like to contribute code, please open a pull request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Highly customizable Discord Rich Presence for MPRIS media players on Linux

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors