Identify the song currently playing in the room (or on any audio stream) by recording a short audio clip on the Music Assistant server and sending it to the AudD music recognition API.
The plugin exposes a single API command:
audd/identify -> RecognitionResult dict
Invoke it from the MA frontend, an automation, or a Home Assistant service call. The plugin handles the recording (via FFmpeg) and the API call; callers get back the recognized artist + title + extras, plus any matches found in the user's configured library providers.
This is a draft / proof of concept — not upstreamed into
music-assistant/server yet.
.
├── audd/ # the plugin itself (drop-in into MA's providers/)
│ ├── __init__.py
│ └── manifest.json
├── Dockerfile # builds a custom MA addon with the plugin baked in
├── config.yaml # HA local-addon manifest
└── README.md
The MA addon's container is rebuilt on each restart, so any file you
docker cp into the running container is wiped. Instead, install this as
a Home Assistant local add-on that bakes the plugin into a custom
image based on ghcr.io/music-assistant/server:latest.
The /addons directory on the HA host is where local add-ons live. Use
the Samba share, Studio Code Server, or SSH add-on to write
files there.
# From an HA shell with /addons mounted:
git clone https://github.com/AudDMusic/audd-music-assistant-plugin.git \
/addons/audd_music_assistantSettings → Add-ons → ⋮ (top-right) → Check for updates (this
triggers a rescan of /addons). A new card "Music Assistant + AudD"
should appear in the Local add-ons section at the top of the store.
Click the new add-on card → Install. HA builds the custom image (takes a couple of minutes on the first build because it has to pull the upstream MA image and bake the plugin in).
When it's done, Start the add-on. It runs on the same ingress port as the upstream MA addon, so the UI is reachable from the same place.
Important: running this side-by-side with the upstream Music Assistant add-on will cause port / mDNS conflicts. Disable the upstream MA add-on before starting this one (or accept that one of the two will fail to bind). The custom add-on has the same MA inside plus the AudD plugin — it isn't meant to coexist with the upstream add-on, it replaces it.
Open Music Assistant → Settings → Providers → Plugins → Add a plugin → AudD Music Recognition. Fill in:
- AudD API Token — get one at https://dashboard.audd.io. The public
token
"test"works for hello-worlds (capped at 10 requests/day). - Audio input (FFmpeg input args) — see examples below.
- Recording duration — default 8 seconds. AudD recognizes best on 5–12 s.
- Provider metadata — comma-separated list of
apple_music,spotify,deezer,napster,musicbrainz. Each adds a small amount of latency.
The plugin registers audd/identify as an MA API command. Call it
however you'd reach any other MA command — HA service call, MA WebSocket
message, or HTTP API. See the API section below.
If you run MA from source or as your own Docker container (not the HA
add-on), just drop audd/ straight into MA's providers folder:
git clone https://github.com/AudDMusic/audd-music-assistant-plugin.git
cp -r audd-music-assistant-plugin/audd \
/path/to/music_assistant/providers/auddFor "MA from source" — see the upstream
DEVELOPMENT.md
to set up the dev environment, then symlink audd/ into
music_assistant/providers/.
For "MA in plain Docker" — bind-mount the plugin folder:
services:
music-assistant:
image: ghcr.io/music-assistant/server:latest
volumes:
- /path/to/audd-music-assistant-plugin/audd:/app/venv/lib/python3.13/site-packages/music_assistant/providers/audd:ro
- ./data:/data
network_mode: host(Adjust the Python version in the path if your image uses a different one.)
The FFmpeg input args field accepts any FFmpeg input spec. Whitespace-separated; shell-style quoting allowed.
| Source | FFmpeg input args |
|---|---|
| PulseAudio default mic | -f pulse -i default |
| Specific PulseAudio source | -f pulse -i alsa_input.usb-FOO-... |
| ALSA device (e.g. USB mic on hw:1) | -f alsa -i hw:1,0 |
| Network audio stream (radio, Icecast, HLS) | -i https://npr-ice.streamguys1.com/live.mp3 |
| Audio file on disk (testing) | -i /media/sample.mp3 |
For HA add-on installs: PulseAudio / ALSA access inside the addon's container requires the host's audio devices to be passed through. The upstream MA addon config does this for some flows; YMMV for a fresh recognition mic. The simplest first test is a network stream input — it needs no audio-device passthrough at all and exercises the full flow (FFmpeg → AudD → result).
The plugin registers a single MA API command:
audd/identify
It takes no arguments and returns:
matched: false with the other fields empty when AudD returns no match.
- Server-side capture only. Browser-microphone capture (sending audio from the MA frontend to the backend) is a separate flow not yet implemented.
- No frontend UI button. The plugin exposes a backend command; invocation today is via an automation, HA service call, or direct API call.
- No validation on FFmpeg input args at config-save time. A misconfigured input arg produces a clean error in MA's logs but doesn't get caught before activation.
- No rate limiting in the plugin. A caller hammering
audd/identifywill consume AudD requests. Add an HA automation cooldown if exposing this to many users.
MIT. The plugin code in this repo is provided under the same terms as the wider Music Assistant project.
{ "matched": true, "artist": "Imagine Dragons", "title": "Warriors", "album": "Warriors", "release_date": "2014-09-18", "label": "Universal Music", "timecode": "02:32", "song_link": "https://lis.tn/Warriors", "isrc": "USUM71411293", "apple_music_url": "https://music.apple.com/...", "spotify_uri": "spotify:track:...", "library_matches": [ { "uri": "spotify://track/...", "name": "Warriors", "artists": ["Imagine Dragons"], "album": "Warriors", "provider": "spotify" } ] }