Music Assistant Provider Types: MusicProvider, PlayerProvider, and MetadataProvider Explained
Music Assistant defines three distinct provider types—MusicProvider, PlayerProvider, and MetadataProvider—that inherit from a common base class to modularize music sources, playback devices, and metadata enrichment.
The Music Assistant server architecture revolves around a pluggable provider system that separates concerns between content discovery, device control, and data enhancement. Each provider type implements a specific contract defined in the music_assistant/models/ directory, allowing developers to extend functionality without modifying core server code. Understanding these Music Assistant provider types is essential for building custom integrations or contributing to the ecosystem.
The Three Core Provider Types
Music Assistant organizes extensions into three categories based on their primary function. Each category has a dedicated abstract base class that defines the required interface and optional feature hooks.
MusicProvider: Content and Library Management
The MusicProvider class handles music catalogue access, search operations, and library synchronization. Located in music_assistant/models/music_provider.py, this provider type supplies tracks, albums, artists, playlists, radios, podcasts, and audiobooks to the system.
Key responsibilities include:
- Library synchronization via
sync_library(), which orchestrates full imports of media items into Music Assistant's central SQLite database - Search functionality through
search()methods that return structured results across media types - Streaming support for generating playable audio streams
- Media item CRUD operations for creating, updating, and deleting library entries
The class uses helper methods like _sync_library_artists() and _sync_library_albums() to perform per-item upserts, genre synchronization, and deletion handling during sync operations.
PlayerProvider: Device Discovery and Control
The PlayerProvider class manages physical or virtual playback devices. Defined in music_assistant/models/player_provider.py, this provider type handles device discovery, grouping, and lifecycle management.
Key capabilities include:
- Player discovery via
discover_players(), though many implementations rely on mDNS/UPnP and use this as a no-op entry point - Enable/disable hooks through
on_player_enabled()andon_player_disabled()callbacks that register or unregister devices with the central controller - Group management for creating and removing player groups
- Feature declaration indicating support for advanced capabilities like gapless playback or volume normalization
The on_player_enabled() hook typically schedules discovery calls using self.mass.call_later(), while on_player_disabled() ensures clean unregistration from the player controller.
MetadataProvider: Data Enrichment and Recommendations
The MetadataProvider class supplies supplementary metadata and recommendation services. Found in music_assistant/models/metadata_provider.py, this provider type enhances media items with external data.
Core functions include:
- Artist and album metadata retrieval via
get_artist_metadata()andget_album_metadata() - Image resolution through
resolve_image()for fetching high-quality artwork - Recommendation engines using
get_similar_tracks()to suggest related content - Default implementations that return
Noneor empty lists, allowing selective override of specific methods
Concrete implementations might fetch data from Last.fm, Discogs, or MusicBrainz to enrich the local library without disrupting core playback functionality.
The Provider Base Class and Shared Architecture
All three provider types inherit from the abstract Provider class in music_assistant/models/provider.py. This base class supplies shared functionality including configuration handling, logging infrastructure, and lifecycle management.
Lifecycle Management
Every provider follows a standardized initialization pattern:
__init__sets up logging, internal caches, and stores the manifest and configuration objectsloaded_in_masstriggers after instantiation, allowing asynchronous initialization and registration with theMusicAssistantcoreunloadenables graceful shutdown and resource cleanup without server restartupdate_configsupports runtime reconfiguration, applying new settings without reloading the provider module
Feature Gating with ProviderFeature
The base class implements feature gating through the ProviderFeature enum. Providers declare supported features in their manifest (e.g., ProviderFeature.SEARCH, ProviderFeature.LIBRARY_TRACKS_EDIT), and the base class validates these flags before invoking optional methods. This ensures the core only calls methods the provider actually implements.
Accessing Core Services
Providers communicate with the Music Assistant core through self.mass, the shared MusicAssistant instance. This object provides access to:
- Caching layer via
self.mass.cache - Music controller through
self.mass.music - Player controller via
self.mass.players - Task scheduling using
self.mass.call_later()andself.mass.create_task()
Implementing Custom Providers
Developers create extensions by subclassing the appropriate provider type and including a manifest.json file specifying the domain, name, type (music, player, or metadata), and supported features.
Creating a Music Provider
# my_custom_provider/__init__.py
from music_assistant.models.music_provider import MusicProvider
from music_assistant_models.enums import ProviderFeature, MediaType
class MyCustomMusicProvider(MusicProvider):
"""A stub provider that only supports searching."""
async def search(self, search_query: str, media_types: list[MediaType], limit: int = 5):
# Pretend we queried an external API and return dummy results
return SearchResults(
artists=[],
albums=[],
tracks=[],
playlists=[],
radios=[],
podcasts=[],
)
# manifest.json (placed next to __init__.py)
{
"domain": "mycustom",
"name": "My Custom Music",
"type": "music",
"stage": "stable",
"features": ["SEARCH"]
}
Implementing a Player Provider
# my_player_provider/__init__.py
from music_assistant.models.player_provider import PlayerProvider
class MyMDNSPlayerProvider(PlayerProvider):
async def discover_players(self):
# Use zeroconf to find "_myplayer._tcp.local." services
await self.mass.run_provider_discovery(self.instance_id)
Building a Metadata Provider
# my_metadata_provider/__init__.py
from music_assistant.models.metadata_provider import MetadataProvider
class MyCoverArtProvider(MetadataProvider):
async def resolve_image(self, path: str):
# Assume `path` is a MusicBrainz ID – retrieve the image URL
url = f"https://coverartarchive.org/release/{path}/front-500.jpg"
return url
Key Source Files and Implementation Details
Understanding the provider architecture requires familiarity with these specific files in the music-assistant/server repository:
| File | Role |
|---|---|
music_assistant/models/provider.py |
Base Provider class with config handling, logging, and lifecycle hooks |
music_assistant/models/music_provider.py |
MusicProvider implementation with library sync and search contracts |
music_assistant/models/player_provider.py |
PlayerProvider definition for device discovery and management |
music_assistant/models/metadata_provider.py |
MetadataProvider interface for enrichment and recommendations |
music_assistant/__main__.py |
Server entrypoint that instantiates the core and loads provider manifests |
music_assistant/constants.py |
Global constants and configuration keys used across providers |
Summary
- MusicProvider handles content catalogues, library synchronization, and audio streaming through methods like
sync_library()andsearch(). - PlayerProvider manages playback devices and groups via
discover_players()and lifecycle hookson_player_enabled()/on_player_disabled(). - MetadataProvider enriches media items with external data using
get_artist_metadata(),resolve_image(), and recommendation methods. - All providers inherit from the base
Providerclass inmusic_assistant/models/provider.py, sharing configuration management, logging, and feature gating capabilities. - The
MusicAssistantcore (self.mass) provides providers with access to controllers, caching, and task scheduling utilities.
Frequently Asked Questions
What is the difference between a MusicProvider and a PlayerProvider in Music Assistant?
A MusicProvider supplies audio content and metadata from external sources like Spotify or local files, handling library synchronization and search. A PlayerProvider manages the physical or virtual devices that actually play the audio, handling discovery, grouping, and device-specific control commands. While MusicProviders deal with "what" to play, PlayerProviders handle "where" it plays.
How does Music Assistant handle provider configuration and lifecycle management?
Providers follow a standardized lifecycle defined in the base Provider class. The __init__ method receives configuration and manifest data, loaded_in_mass() triggers asynchronous initialization, and unload() enables graceful shutdown. The update_config() method allows runtime reconfiguration without restarting the server, checking feature support against declared ProviderFeature flags before invoking optional methods.
Can a single provider implementation serve multiple provider types?
No, each provider implementation must inherit from a specific base class—MusicProvider, PlayerProvider, or MetadataProvider—and declare its type in the manifest.json file using the type field ("music", "player", or "metadata"). While providers cannot hybridize types, they can communicate with other provider types through the shared MusicAssistant instance (self.mass) to coordinate behavior.
What methods are required when implementing a MetadataProvider?
No methods are strictly required because MetadataProvider provides default implementations that return None or empty lists. Developers typically override specific methods based on their data source, such as get_artist_metadata() for biographical data, resolve_image() for artwork URLs, or get_similar_tracks() for recommendation engines. This selective implementation allows lightweight providers that only enhance specific media types.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →