Skip to content

ci: add riscv64 builds#4949

Merged
deluan merged 2 commits intonavidrome:masterfrom
MichaIng:riscv64
Jan 31, 2026
Merged

ci: add riscv64 builds#4949
deluan merged 2 commits intonavidrome:masterfrom
MichaIng:riscv64

Conversation

@MichaIng
Copy link
Contributor

Description

riscv64 builds are added to CI, using new taglib builds for this architecture:

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor
  • Other (please describe):

Checklist

Please review and check all that apply:

  • My code follows the project’s coding style
  • I have tested the changes locally
  • I have added or updated documentation as needed
  • I have added tests that prove my fix/feature works (or explain why not)
  • All existing and new tests pass

How to Test

  • Tests and full CI passes
  • riscv64 binary is compiled and added as asset to PR/release
  • riscv64 tarball executes successfully on RISC-V hardware

Screenshots / Demos (if applicable)

Additional Notes

This requires at least Debian Trixie base systems, and a cross-taglib version with riscv64 release assets.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @MichaIng, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request expands the project's build capabilities by integrating riscv64 architecture support into the CI/CD pipeline. This enhancement allows for the generation of binaries compatible with RISC-V hardware, achieved through strategic updates to Docker build environments and the release configuration, ensuring broader platform availability.

Highlights

  • RISC-V Architecture Support: This pull request introduces support for riscv64 architecture builds within the Continuous Integration (CI) pipeline.
  • Dependency Updates: The Dockerfile has been updated to use newer base images, specifically Alpine Linux 3.23 and Debian Trixie for the Golang build stage, to facilitate riscv64 compatibility. The CROSS_TAGLIB_VERSION has also been updated to 2.1.1-2.
  • Goreleaser Configuration: The release/goreleaser.yml configuration has been modified to include linux_riscv64 as a target architecture for builds.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/pipeline.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request successfully adds riscv64 builds to the CI pipeline by updating base Docker images to newer versions (Alpine 3.23, Golang 1.25-trixie) and incorporating the necessary CROSS_TAGLIB_VERSION for riscv64 support. The goreleaser.yml has also been correctly updated to include linux_riscv64 as a build target. The changes are well-aligned with the stated goal of the pull request.

Copy link
Member

@deluan deluan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but check my comment.

Dockerfile Outdated
########################################################################################################################
### Build Final Image
FROM public.ecr.aws/docker/library/alpine:3.20 AS final
FROM public.ecr.aws/docker/library/alpine:3.23 AS final
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to be 3.23? I'm trying to stay on the oldest supported alpine image, as it creates smaller images, and we don't actually need it to be on the latest, as long as it is maintained. Currently this is 3.20

Copy link
Contributor Author

@MichaIng MichaIng Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should work with Alpine 3.20 as well, which is in fact the first version with riscv64 support. Let's just try it.

EDIT: In case it is relevant for cross-taglib as well: if the builds succeed here with Alpine 3.20, then it could be reverted for the cross-taglib CI as well.

EDIT2: Looks good, but package sizes seem to be the same:

I can test them on RISC-V hardware tomorrow, just to be failsafe, but need to sleep now 😴.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to the Navidrome Docker images created from the Alpine images, not the binaries. Will you also be able to test the Docker Images?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah makes sense. I added a DOCKER_HUB_USERNAME secret to my repo and reopened a PR there, which hopefully triggers the Docker image builds and upload to GHCR, so I can test them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! If you have issues, I pushed it to deluan/navidrome:pr-4949

Copy link
Contributor Author

@MichaIng MichaIng Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERROR: failed to parse ref "ghcr.io/MichaIng/navidrome": invalid reference format: repository name (MichaIng/navidrome) must be lowercase

It seems to conflict with uppercase GitHub user/orga names 🤔. Not sure whether it can be forced lower-case somehow, otherwise I would need to change the way images are built and upload. Probably fine to test after merge, once images have been uploaded to your GHCR repo?

EDIT: Ah, saw your comment just now. Great, about to test them!

The DEB package works fine:

Jan 29 20:20:39 Star64 systemd[1]: Started navidrome.service - Your Personal Streaming Service.
Jan 29 20:20:39 Star64 navidrome[5340]:  _   _             _     _
Jan 29 20:20:39 Star64 navidrome[5340]: | \ | |           (_)   | |
Jan 29 20:20:39 Star64 navidrome[5340]: |  \| | __ ___   ___  __| |_ __ ___  _ __ ___   ___
Jan 29 20:20:39 Star64 navidrome[5340]: | . ` |/ _` \ \ / / |/ _` | '__/ _ \| '_ ` _ \ / _ \
Jan 29 20:20:39 Star64 navidrome[5340]: | |\  | (_| |\ V /| | (_| | | | (_) | | | | | |  __/
Jan 29 20:20:39 Star64 navidrome[5340]: \_| \_/\__,_| \_/ |_|\__,_|_|  \___/|_| |_| |_|\___|
Jan 29 20:20:39 Star64 navidrome[5340]:          Version: 0.59.0-SNAPSHOT (pr-4949/491af2ff)
Jan 29 20:20:39 Star64 navidrome[5340]: time="2026-01-29T20:20:39+01:00" level=info msg="Loaded configuration" file=/etc/navidrome/navidrome.toml
Jan 29 20:20:39 Star64 navidrome[5340]: time="2026-01-29T20:20:39+01:00" level=info msg="Creating DB Schema"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Starting signaler"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Creating Image cache" maxSize="100 MB" path=/var/lib/navidrome/cache/images
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Starting Insight Collector"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Scheduling DB optimizer" schedule="@every 24h"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Starting scheduler"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Periodic scan is DISABLED"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Periodic backup is DISABLED"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Finished initializing cache" cache=Image elapsedTime=1.1ms maxSize=100MB
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Creating Transcoding cache" maxSize="100 MB" path=/var/lib/navidrome/cache/transcoding
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Finished initializing cache" cache=Transcoding elapsedTime="792.223µs" maxSize=100MB
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Started watcher for library" libraryID=1 name="Music Library" path=/opt/navidrome/music
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Watcher started for library" absoluteLibPath=/opt/navidrome/music libraryID=1 name="Music Library" path=/opt/navidrome/music
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Running initial setup"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Setting Session Timeout" value=48h
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Creating new JWT secret, used for encrypting UI sessions"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Login rate limit set" requestLimit=5 windowLength=2
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Found ffmpeg" path=/usr/bin/ffmpeg
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Spotify integration is not enabled: missing ID/Secret"
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting Native API routes" path=/api
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting Subsonic API routes" path=/rest
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting Public Endpoints routes" path=/share
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting LastFM Auth routes" path=/api/lastfm
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting ListenBrainz Auth routes" path=/api/listenbrainz
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting Background images routes" path=/backgrounds
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Creating backgrounds cache" maxSize="100 MB" path=/var/lib/navidrome/cache/backgrounds
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Mounting WebUI routes" path=/app
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="Finished initializing cache" cache=backgrounds elapsedTime="842.471µs" maxSize=100MB
Jan 29 20:20:43 Star64 navidrome[5340]: time="2026-01-29T20:20:43+01:00" level=info msg="----> Navidrome server is ready!" address="0.0.0.0:4533" startupTime=4.05s tlsEnabled=false
Jan 29 20:20:45 Star64 navidrome[5340]: time="2026-01-29T20:20:45+01:00" level=warning msg="Full scan required after migration"
Jan 29 20:20:45 Star64 navidrome[5356]: time="2026-01-29T20:20:45+01:00" level=info msg="Loaded configuration" file=/etc/navidrome/navidrome.toml
Jan 29 20:20:45 Star64 navidrome[5356]: time="2026-01-29T20:20:45+01:00" level=info msg="Scanner: Starting scan" fullScan=true numLibraries=1
Jan 29 20:20:45 Star64 navidrome[5356]: time="2026-01-29T20:20:45+01:00" level=warning msg="Playlists will not be imported, as there are no admin users yet, Please create an admin user first, and then update the playlists for them to be imported"
Jan 29 20:20:45 Star64 navidrome[5356]: time="2026-01-29T20:20:45+01:00" level=info msg="Scanner: Finished scanning all libraries" duration=114.8ms
Jan 29 20:20:45 Star64 navidrome[5340]: time="2026-01-29T20:20:45+01:00" level=info msg="Scan completed"
root@Star64:/tmp# ss -tlpn
State                             Recv-Q                             Send-Q                                                         Local Address:Port                                                         Peer Address:Port                            Process
LISTEN                            0                                  1000                                                                 0.0.0.0:22                                                                0.0.0.0:*                                users:(("dropbear",pid=2213,fd=3))
LISTEN                            0                                  1000                                                                    [::]:22                                                                   [::]:*                                users:(("dropbear",pid=2213,fd=4))
LISTEN                            0                                  4096                                                                       *:4533                                                                    *:*                                users:(("navidrome",pid=5340,fd=16))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know when/if it is ok to merge this

This requires at least Debian Trixie base systems, and a cross-taglib version with riscv64 release assets.

Signed-off-by: MichaIng <micha@dietpi.com>
…glib version

Signed-off-by: Deluan <deluan@navidrome.org>
@MichaIng
Copy link
Contributor Author

Sorry for the delay. I recognized that my kernel was missing some features for running Docker containers, and it was old anyway. So I invested some time to move to more recent Linux, which needed some 3rd party driver updates as well etc. But now, the container seems to run well:

time="2026-01-31T00:26:01Z" level=info msg="No configuration file found. Loaded configuration only from environment variables"
time="2026-01-31T00:26:02Z" level=info msg="Creating DB Schema"
time="2026-01-31T00:26:05Z" level=info msg="Starting signaler"
time="2026-01-31T00:26:05Z" level=info msg="Running initial setup"
time="2026-01-31T00:26:05Z" level=info msg="Setting Session Timeout" value=48h
time="2026-01-31T00:26:05Z" level=info msg="Creating new JWT secret, used for encrypting UI sessions"
time="2026-01-31T00:26:05Z" level=info msg="Periodic scan is DISABLED"
time="2026-01-31T00:26:05Z" level=info msg="Creating Image cache" maxSize="100 MB" path=/data/cache/images
time="2026-01-31T00:26:05Z" level=info msg="Starting scheduler"
time="2026-01-31T00:26:05Z" level=info msg="Periodic backup is DISABLED"
time="2026-01-31T00:26:05Z" level=info msg="Starting Insight Collector"
time="2026-01-31T00:26:05Z" level=info msg="Finished initializing cache" cache=Image elapsedTime=21.1ms maxSize=100MB
time="2026-01-31T00:26:05Z" level=info msg="Scheduling DB optimizer" schedule="@every 24h"
time="2026-01-31T00:26:05Z" level=info msg="Creating Transcoding cache" maxSize="100 MB" path=/data/cache/transcoding
time="2026-01-31T00:26:05Z" level=info msg="Finished initializing cache" cache=Transcoding elapsedTime="830.75µs" maxSize=100MB
time="2026-01-31T00:26:05Z" level=info msg="Started watcher for library" libraryID=1 name="Music Library" path=/music
time="2026-01-31T00:26:05Z" level=info msg="Watcher started for library" absoluteLibPath=/music libraryID=1 name="Music Library" path=/music
time="2026-01-31T00:26:05Z" level=info msg="Login rate limit set" requestLimit=5 windowLength=2
time="2026-01-31T00:26:05Z" level=info msg="Found ffmpeg" path=/usr/bin/ffmpeg
time="2026-01-31T00:26:05Z" level=info msg="Spotify integration is not enabled: missing ID/Secret"
time="2026-01-31T00:26:05Z" level=info msg="Mounting Native API routes" path=/api
time="2026-01-31T00:26:05Z" level=info msg="Mounting Subsonic API routes" path=/rest
time="2026-01-31T00:26:05Z" level=info msg="Mounting Public Endpoints routes" path=/share
time="2026-01-31T00:26:05Z" level=info msg="Mounting LastFM Auth routes" path=/api/lastfm
time="2026-01-31T00:26:05Z" level=info msg="Mounting ListenBrainz Auth routes" path=/api/listenbrainz
time="2026-01-31T00:26:05Z" level=info msg="Mounting Background images routes" path=/backgrounds
time="2026-01-31T00:26:05Z" level=info msg="Mounting WebUI routes" path=/app
time="2026-01-31T00:26:05Z" level=info msg="Creating backgrounds cache" maxSize="100 MB" path=/data/cache/backgrounds
time="2026-01-31T00:26:05Z" level=info msg="Finished initializing cache" cache=backgrounds elapsedTime=1.4ms maxSize=100MB
time="2026-01-31T00:26:05Z" level=info msg="----> Navidrome server is ready!" address="0.0.0.0:4533" startupTime=3.73s tlsEnabled=false
time="2026-01-31T00:26:07Z" level=warning msg="Full scan required after migration"
time="2026-01-31T00:26:07Z" level=info msg="No configuration file found. Loaded configuration only from environment variables"
time="2026-01-31T00:26:07Z" level=info msg="Scanner: Starting scan" fullScan=true numLibraries=1
time="2026-01-31T00:26:07Z" level=warning msg="Playlists will not be imported, as there are no admin users yet, Please create an admin user first, and then update the playlists for them to be imported"
time="2026-01-31T00:26:07Z" level=info msg="Scanner: Finished scanning all libraries" duration=37.4ms
time="2026-01-31T00:26:07Z" level=info msg="Scan completed"

Web UI works as well. But I did not test actual playback.

@deluan
Copy link
Member

deluan commented Jan 31, 2026

No worries. Thanks for validating.

@deluan deluan merged commit 84ab652 into navidrome:master Jan 31, 2026
36 checks passed
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Feb 3, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [deluan/navidrome](https://github.com/navidrome/navidrome) | minor | `0.59.0` → `0.60.0` |

---

### Release Notes

<details>
<summary>navidrome/navidrome (deluan/navidrome)</summary>

### [`v0.60.0`](https://github.com/navidrome/navidrome/releases/tag/v0.60.0)

[Compare Source](navidrome/navidrome@v0.59.0...v0.60.0)

#### Plugins

This release introduces a major rewrite of the experimental **Plugin System**, now with multi-language PDK support, enabling developers to extend Navidrome's functionality using WebAssembly-based plugins written in Go, Rust, Python or JavaScript. Plugins run in a secure sandbox and can provide additional metadata sources, custom integrations, and server-side enhancements. Users can now easily configure plugins directly from the UI through a new JSONForms-based configuration interface.

A couple of working plugins are already available:

- [AudioMuse-AI integration](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin)
- [ListenBrainz Daily Playlist Importer](https://github.com/kgarner7/navidrome-listenbrainz-daily-playlist)
- [Discord Rich Presence](https://github.com/navidrome/discord-rich-presence-plugin)

For more plugins, keep an eye on the tag [navidrome-plugins](https://github.com/topics/navidrome-plugin) in GitHub.

More details and instructions on how to use and manage plugins can be found in our [documentation](https://www.navidrome.org/docs/usage/features/plugins/).
New documentation will soon be added with details on how to create new plugins.

#### Metadata Extraction

Additionally, this version includes a **pure-Go metadata extractor** built on top of the new `go-taglib` library. This is a significant step toward removing the C++ TagLib dependency, which will simplify cross-platform builds and packaging in future releases. The new extractor is activated by default, but in case of any issues you can revert to the previous implementation by setting `Scanner.Extractor="legacy-taglib"` configuration option.

#### Instant Mix

The Instant Mix feature generates a playlist of similar songs based on a selected track. By default, it retrieves similar songs from Last.fm (if configured with an API key) or falls back to Deezer. It can also be configured to use external plugins, like [AudioMuse-AI](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin) for sonic analysis-based similarity recommendations.

#### New and Changed Configuration Options

##### Plugin System Options

| Option               | Default   | Description                                                   |
| -------------------- | --------- | ------------------------------------------------------------- |
| `Plugins.Enabled`    | `true`    | Enable/disable the plugin system                              |
| `Plugins.Folder`     | `""`      | Path to the plugins directory. Default: `$DataFolder/Plugins` |
| `Plugins.CacheSize`  | `"200MB"` | Maximum cache size for storing compiled plugin WASM modules   |
| `Plugins.AutoReload` | `false`   | Automatically detect new/changed/removed plugins              |
| `Plugins.LogLevel`   | `""`      | Override log level for plugin-related messages                |

##### Subsonic API Options

| Option                         | Default | Description                                                                                                                    |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Subsonic.MinimalClients`      | `""`    | Comma-separated list of clients that receive reduced API responses (useful for resource-constrained devices like smartwatches) |
| `Subsonic.EnableAverageRating` | `true`  | Include average rating in API responses                                                                                        |

##### Metadata & Matching Options

| Option                       | Default | Description                                                                                        |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `SimilarSongsMatchThreshold` | `85`    | Minimum similarity score (0-100) for matching similar songs from external sources to local library |
| `LastFM.Language`            | `"en"`  | Now supports comma-separated list of languages (e.g., `"de,fr,en"`) for metadata fallback          |
| `Deezer.Language`            | `"en"`  | Now supports comma-separated list of languages for metadata fallback                               |

##### Renamed Options (Deprecation Notice)

The following options have been renamed. The old names still work but will be removed in a future release:

| Old Name                                      | New Name                   |
| --------------------------------------------- | -------------------------- |
| `HTTPSecurityHeaders.CustomFrameOptionsValue` | `HTTPHeaders.FrameOptions` |

#### Security

- Fix potential XSS vulnerability by sanitizing user-supplied data before rendering (GHSA-rh3r-8pxm-hg4w). ([d7ec735](navidrome/navidrome@d7ec7355c) by [@&#8203;AlexGustafsson](https://github.com/AlexGustafsson))
- Fix potential DoS vulnerability in cover art upscaling by clamping requested square size to original dimensions (GHSA-hrr4-3wgr-68x3). ([77367548](navidrome/navidrome@77367548f) by [@&#8203;deluan](https://github.com/deluan)). Thanks to [@&#8203;yunfachi](https://github.com/yunfachi)

#### Added

- Plugins:
  - Add new WebAssembly-based plugin system with multi-language PDK support (Go, Rust, Python). ([#&#8203;4833](navidrome/navidrome#4833) by [@&#8203;deluan](https://github.com/deluan))
  - Add JSONForms-based plugin configuration UI. ([#&#8203;4911](navidrome/navidrome#4911) by [@&#8203;deluan](https://github.com/deluan))
  - Add similar songs retrieval functions to plugins API. ([#&#8203;4933](navidrome/navidrome#4933) by [@&#8203;deluan](https://github.com/deluan))

- Server:
  - Add pure-Go metadata extractor (`go-taglib`) as alternative to FFmpeg-based extraction. ([#&#8203;4902](navidrome/navidrome#4902) by [@&#8203;deluan](https://github.com/deluan))
  - Add support for reading embedded images using the new taglib extractor by default. ([66474fc](navidrome/navidrome@66474fc9f) by [@&#8203;deluan](https://github.com/deluan))
  - Add Instant Mix (song-based Similar Songs) functionality with MBID, ISRC and Title/Artist fuzzy matching. ([#&#8203;4919](navidrome/navidrome#4919), [#&#8203;4946](navidrome/navidrome#4946) by [@&#8203;deluan](https://github.com/deluan))
  - Add support for multiple languages when fetching metadata from Last.fm and Deezer. ([#&#8203;4952](navidrome/navidrome#4952) by [@&#8203;deluan](https://github.com/deluan))
  - Add `Subsonic.MinimalClients` configuration option for improved compatibility with minimal Subsonic clients. Default list is `"SubMusic"` ([#&#8203;4850](navidrome/navidrome#4850) by [@&#8203;typhoon2099](https://github.com/typhoon2099))
  - Add support for public/private playlists in NSP import. ([c5447a6](navidrome/navidrome@c5447a637) by [@&#8203;deluan](https://github.com/deluan))
  - Add RISCV64 builds. ([#&#8203;4949](navidrome/navidrome#4949) by [@&#8203;MichaIng](https://github.com/MichaIng))

- UI Features:
  - Add composer field to table views. ([#&#8203;4857](navidrome/navidrome#4857) by [@&#8203;AlexGustafsson](https://github.com/AlexGustafsson))
  - Add prompt before closing window if music is playing. ([#&#8203;4899](navidrome/navidrome#4899) by [@&#8203;alannnna](https://github.com/alannnna))
  - Add Nautiline-like theme. ([#&#8203;4909](navidrome/navidrome#4909) by [@&#8203;borisrorsvort](https://github.com/borisrorsvort))
  - Add multiline support and resizing for playlist comment input. ([6fce30c](navidrome/navidrome@6fce30c13) by [@&#8203;deluan](https://github.com/deluan))

- Subsonic API:
  - Add `avgRating` field from Subsonic spec. ([#&#8203;4900](navidrome/navidrome#4900) by [@&#8203;terry90](https://github.com/terry90))

- Insights:
  - Add insights collection for Scanner.Extractor configuration to measure go-taglib usage. ([63517e9](navidrome/navidrome@63517e904) by [@&#8203;deluan](https://github.com/deluan))
  - Add file suffix counting to insights. ([0473c50](navidrome/navidrome@0473c50b4) by [@&#8203;deluan](https://github.com/deluan))

#### Changed

- Optimize cross-library move detection for single-library setups. ([#&#8203;4888](navidrome/navidrome#4888) by [@&#8203;deluan](https://github.com/deluan))
- Improve Deezer artist search ranking. ([a081569](navidrome/navidrome@a081569ed) by [@&#8203;deluan](https://github.com/deluan))
- Rename `HTTPSecurityHeaders.CustomFrameOptionsValue` to `HTTPHeaders.FrameOptions`. ([7ccf44b](navidrome/navidrome@7ccf44b8e) by [@&#8203;deluan](https://github.com/deluan))
- Update translations: Bulgarian, Catalan, German, Greek, Spanish, Finnish, French, Galician, Indonesian, Dutch, Polish, Russian, Slovenian, Swedish, Thai by [POEditor contributors](https://www.navidrome.org/docs/developers/translations/).
- Update Spanish translations. ([#&#8203;4904](navidrome/navidrome#4904) by [@&#8203;abrugues](https://github.com/abrugues))
- Update Basque translation. ([#&#8203;4815](navidrome/navidrome#4815) by [@&#8203;xabirequejo](https://github.com/xabirequejo))

#### Fixed

- Playlists:
  - Fix M3U playlist import failing for paths with different UTF/Unicode representations (NFC/NFD normalization). ([#&#8203;4890](navidrome/navidrome#4890) by [@&#8203;deluan](https://github.com/deluan))
  - Fix playlist name sorting to be case-insensitive. ([#&#8203;4845](navidrome/navidrome#4845) by [@&#8203;deluan](https://github.com/deluan))

- UI:
  - Fix various UI issues and improve styling coherence. ([#&#8203;4910](navidrome/navidrome#4910) by [@&#8203;borisrorsvort](https://github.com/borisrorsvort))
  - Fix AMusic theme player buttons and delete button color. ([#&#8203;4797](navidrome/navidrome#4797) by [@&#8203;dragonish](https://github.com/dragonish))
  - Fix export missing files showing only first 1000 results. ([017676c](navidrome/navidrome@017676c45) by [@&#8203;deluan](https://github.com/deluan))

- Scanner:
  - Fix `FullScanInProgress` not reflecting current scan request during interrupted scans. ([8c80be5](navidrome/navidrome@8c80be56d) by [@&#8203;deluan](https://github.com/deluan))
  - Fix "Expression tree is too large" error by executing GetFolderUpdateInfo in batches. ([cde5992](navidrome/navidrome@cde5992c4) by [@&#8203;deluan](https://github.com/deluan))
  - Fix stale role associations when artist role changes. ([2d7b716](navidrome/navidrome@2d7b71683) by [@&#8203;deluan](https://github.com/deluan))
  - Fix infinite recursion in PID configuration. ([1c4a7e8](navidrome/navidrome@1c4a7e855) by [@&#8203;deluan](https://github.com/deluan))
  - Fix default PIDs not being set for Album and Track. In some circumstances it could lead to empty PIDs ([71f549a](navidrome/navidrome@71f549afb) by [@&#8203;deluan](https://github.com/deluan))
  - Fix error when watcher detected too many folder changes, causing the scan to fail. ([9ed309a](navidrome/navidrome@9ed309ac8) by [@&#8203;deluan](https://github.com/deluan))
  - Show scan errors in the UI more consistently. ([ebbc31f](navidrome/navidrome@ebbc31f1a) by [@&#8203;deluan](https://github.com/deluan))

- Subsonic API:
  - Fix username parameter validation for `getUser` endpoint. ([6ed6524](navidrome/navidrome@6ed652475) by [@&#8203;deluan](https://github.com/deluan))
  - Fix `getNowPlaying` endpoint to always be enabled regardless of configuration. ([603cccd](navidrome/navidrome@603cccde1) by [@&#8203;deluan](https://github.com/deluan))

- Server:
  - Fix JWT-related errors being exposed on share page. ([#&#8203;4892](navidrome/navidrome#4892) by [@&#8203;AlexGustafsson](https://github.com/AlexGustafsson))
  - Fix user context not preserved in async NowPlaying dispatch. ([396eee4](navidrome/navidrome@396eee48c) by [@&#8203;deluan](https://github.com/deluan))
  - Fix environment variable configuration loading not being logged when no config file is found. ([51ca2de](navidrome/navidrome@51ca2dee6) by [@&#8203;deluan](https://github.com/deluan))
  - Fix items with no annotation not being included for `starred=false` filter, handle `has_rating=false`. ([#&#8203;4921](navidrome/navidrome#4921) by [@&#8203;kgarner7](https://github.com/kgarner7))
  - Last.fm's `scrobble` and `updateNowPlaying` methods should send parameters in request body. ([51026de](navidrome/navidrome@51026de80) by [@&#8203;deluan](https://github.com/deluan))

#### New Contributors

- [@&#8203;alannnna](https://github.com/alannnna) made their first contribution in [#&#8203;4899](navidrome/navidrome#4899)
- [@&#8203;abrugues](https://github.com/abrugues) made their first contribution in [#&#8203;4904](navidrome/navidrome#4904)
- [@&#8203;AlexGustafsson](https://github.com/AlexGustafsson) made their first contribution in [#&#8203;4857](navidrome/navidrome#4857)
- [@&#8203;borisrorsvort](https://github.com/borisrorsvort) made their first contribution in [#&#8203;4909](navidrome/navidrome#4909)
- [@&#8203;dragonish](https://github.com/dragonish) made their first contribution in [#&#8203;4797](navidrome/navidrome#4797)
- [@&#8203;MichaIng](https://github.com/MichaIng) made their first contribution in [#&#8203;4949](navidrome/navidrome#4949)
- [@&#8203;terry90](https://github.com/terry90) made their first contribution in [#&#8203;4900](navidrome/navidrome#4900)
- [@&#8203;typhoon2099](https://github.com/typhoon2099) made their first contribution in [#&#8203;4850](navidrome/navidrome#4850)

**Full Changelog**: <navidrome/navidrome@v0.59.0...v0.60.0>

#### Helping out

This release is only possible thanks to the support of some **awesome people**!

Want to be one of them?
You can [sponsor](https://github.com/sponsors/deluan), pay me a [Ko-fi](https://ko-fi.com/deluan),
or [contribute with code](https://www.navidrome.org/docs/developers/).

#### Where to go next?

- Read installation instructions on our [website](https://www.navidrome.org/docs/installation/).
- Host Navidrome on [PikaPods](https://www.pikapods.com/pods/navidrome) for a simple cloud solution.
- Reach out on [Discord](https://discord.gg/xh7j7yF), [Reddit](https://www.reddit.com/r/navidrome/)
  and [Twitter](https://twitter.com/navidrome)!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4wLjIiLCJ1cGRhdGVkSW5WZXIiOiI0My4wLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImltYWdlIl19-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/3687
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
renovate bot added a commit to sdwilsh/ansible-playbooks that referenced this pull request Feb 9, 2026
##### [\`0.60.0\`](https://github.com/navidrome/navidrome/releases/tag/v0.60.0)

##### Plugins

This release introduces a major rewrite of the experimental **Plugin System**, now with multi-language PDK support, enabling developers to extend Navidrome's functionality using WebAssembly-based plugins written in Go, Rust, Python or JavaScript. Plugins run in a secure sandbox and can provide additional metadata sources, custom integrations, and server-side enhancements. Users can now easily configure plugins directly from the UI through a new JSONForms-based configuration interface.

A couple of working plugins are already available:

- [AudioMuse-AI integration](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin)
- [ListenBrainz Daily Playlist Importer](https://github.com/kgarner7/navidrome-listenbrainz-daily-playlist)
- [Discord Rich Presence](https://github.com/navidrome/discord-rich-presence-plugin)

For more plugins, keep an eye on the tag [navidrome-plugins](https://github.com/topics/navidrome-plugin) in GitHub.

More details and instructions on how to use and manage plugins can be found in our [documentation](https://www.navidrome.org/docs/usage/features/plugins/).
New documentation will soon be added with details on how to create new plugins.

##### Metadata Extraction

Additionally, this version includes a **pure-Go metadata extractor** built on top of the new `go-taglib` library. This is a significant step toward removing the C++ TagLib dependency, which will simplify cross-platform builds and packaging in future releases. The new extractor is activated by default, but in case of any issues you can revert to the previous implementation by setting `Scanner.Extractor="legacy-taglib"` configuration option.

##### Instant Mix

The Instant Mix feature generates a playlist of similar songs based on a selected track. By default, it retrieves similar songs from Last.fm (if configured with an API key) or falls back to Deezer. It can also be configured to use external plugins, like [AudioMuse-AI](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin) for sonic analysis-based similarity recommendations.

##### New and Changed Configuration Options

##### Plugin System Options

| Option               | Default   | Description                                                   |
| -------------------- | --------- | ------------------------------------------------------------- |
| `Plugins.Enabled`    | `true`    | Enable/disable the plugin system                              |
| `Plugins.Folder`     | `""`      | Path to the plugins directory. Default: `$DataFolder/Plugins` |
| `Plugins.CacheSize`  | `"200MB"` | Maximum cache size for storing compiled plugin WASM modules   |
| `Plugins.AutoReload` | `false`   | Automatically detect new/changed/removed plugins              |
| `Plugins.LogLevel`   | `""`      | Override log level for plugin-related messages                |

##### Subsonic API Options

| Option                         | Default | Description                                                                                                                    |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Subsonic.MinimalClients`      | `""`    | Comma-separated list of clients that receive reduced API responses (useful for resource-constrained devices like smartwatches) |
| `Subsonic.EnableAverageRating` | `true`  | Include average rating in API responses                                                                                        |

##### Metadata & Matching Options

| Option                       | Default | Description                                                                                        |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `SimilarSongsMatchThreshold` | `85`    | Minimum similarity score (0-100) for matching similar songs from external sources to local library |
| `LastFM.Language`            | `"en"`  | Now supports comma-separated list of languages (e.g., `"de,fr,en"`) for metadata fallback          |
| `Deezer.Language`            | `"en"`  | Now supports comma-separated list of languages for metadata fallback                               |

##### Renamed Options (Deprecation Notice)

The following options have been renamed. The old names still work but will be removed in a future release:

| Old Name                                      | New Name                   |
| --------------------------------------------- | -------------------------- |
| `HTTPSecurityHeaders.CustomFrameOptionsValue` | `HTTPHeaders.FrameOptions` |

##### Security

- Fix potential XSS vulnerability by sanitizing user-supplied data before rendering ([GHSA-rh3r-8pxm-hg4w](GHSA-rh3r-8pxm-hg4w)). ([d7ec735](navidrome/navidrome@d7ec7355c) by [@AlexGustafsson](https://github.com/AlexGustafsson))
- Fix potential DoS vulnerability in cover art upscaling by clamping requested square size to original dimensions ([GHSA-hrr4-3wgr-68x3](GHSA-hrr4-3wgr-68x3)). ([77367548](navidrome/navidrome@77367548f) by [@deluan](https://github.com/deluan)). Thanks to [@yunfachi](https://github.com/yunfachi)

##### Added

- Plugins:
  - Add new WebAssembly-based plugin system with multi-language PDK support (Go, Rust, Python). ([#4833](navidrome/navidrome#4833) by [@deluan](https://github.com/deluan))
  - Add JSONForms-based plugin configuration UI. ([#4911](navidrome/navidrome#4911) by [@deluan](https://github.com/deluan))
  - Add similar songs retrieval functions to plugins API. ([#4933](navidrome/navidrome#4933) by [@deluan](https://github.com/deluan))

- Server:
  - Add pure-Go metadata extractor (`go-taglib`) as alternative to FFmpeg-based extraction. ([#4902](navidrome/navidrome#4902) by [@deluan](https://github.com/deluan))
  - Add support for reading embedded images using the new taglib extractor by default. ([66474fc](navidrome/navidrome@66474fc9f) by [@deluan](https://github.com/deluan))
  - Add Instant Mix (song-based Similar Songs) functionality with MBID, ISRC and Title/Artist fuzzy matching. ([#4919](navidrome/navidrome#4919), [#4946](navidrome/navidrome#4946) by [@deluan](https://github.com/deluan))
  - Add support for multiple languages when fetching metadata from Last.fm and Deezer. ([#4952](navidrome/navidrome#4952) by [@deluan](https://github.com/deluan))
  - Add `Subsonic.MinimalClients` configuration option for improved compatibility with minimal Subsonic clients. Default list is `"SubMusic"` ([#4850](navidrome/navidrome#4850) by [@typhoon2099](https://github.com/typhoon2099))
  - Add support for public/private playlists in NSP import. ([c5447a6](navidrome/navidrome@c5447a637) by [@deluan](https://github.com/deluan))
  - Add RISCV64 builds. ([#4949](navidrome/navidrome#4949) by [@MichaIng](https://github.com/MichaIng))

- UI Features:
  - Add composer field to table views. ([#4857](navidrome/navidrome#4857) by [@AlexGustafsson](https://github.com/AlexGustafsson))
  - Add prompt before closing window if music is playing. ([#4899](navidrome/navidrome#4899) by [@alannnna](https://github.com/alannnna))
  - Add Nautiline-like theme. ([#4909](navidrome/navidrome#4909) by [@borisrorsvort](https://github.com/borisrorsvort))
  - Add multiline support and resizing for playlist comment input. ([6fce30c](navidrome/navidrome@6fce30c13) by [@deluan](https://github.com/deluan))

- Subsonic API:
  - Add `avgRating` field from Subsonic spec. ([#4900](navidrome/navidrome#4900) by [@terry90](https://github.com/terry90))

- Insights:
  - Add insights collection for Scanner.Extractor configuration to measure go-taglib usage. ([63517e9](navidrome/navidrome@63517e904) by [@deluan](https://github.com/deluan))
  - Add file suffix counting to insights. ([0473c50](navidrome/navidrome@0473c50b4) by [@deluan](https://github.com/deluan))

##### Changed

- Optimize cross-library move detection for single-library setups. ([#4888](navidrome/navidrome#4888) by [@deluan](https://github.com/deluan))
- Improve Deezer artist search ranking. ([a081569](navidrome/navidrome@a081569ed) by [@deluan](https://github.com/deluan))
- Rename `HTTPSecurityHeaders.CustomFrameOptionsValue` to `HTTPHeaders.FrameOptions`. ([7ccf44b](navidrome/navidrome@7ccf44b8e) by [@deluan](https://github.com/deluan))
- Update translations: Bulgarian, Catalan, German, Greek, Spanish, Finnish, French, Galician, Indonesian, Dutch, Polish, Russian, Slovenian, Swedish, Thai by [POEditor contributors](https://www.navidrome.org/docs/developers/translations/).
- Update Spanish translations. ([#4904](navidrome/navidrome#4904) by [@abrugues](https://github.com/abrugues))
- Update Basque translation. ([#4815](navidrome/navidrome#4815) by [@xabirequejo](https://github.com/xabirequejo))

##### Fixed

- Playlists:
  - Fix M3U playlist import failing for paths with different UTF/Unicode representations (NFC/NFD normalization). ([#4890](navidrome/navidrome#4890) by [@deluan](https://github.com/deluan))
  - Fix playlist name sorting to be case-insensitive. ([#4845](navidrome/navidrome#4845) by [@deluan](https://github.com/deluan))

- UI:
  - Fix various UI issues and improve styling coherence. ([#4910](navidrome/navidrome#4910) by [@borisrorsvort](https://github.com/borisrorsvort))
  - Fix AMusic theme player buttons and delete button color. ([#4797](navidrome/navidrome#4797) by [@dragonish](https://github.com/dragonish))
  - Fix export missing files showing only first 1000 results. ([017676c](navidrome/navidrome@017676c45) by [@deluan](https://github.com/deluan))

- Scanner:
  - Fix `FullScanInProgress` not reflecting current scan request during interrupted scans. ([8c80be5](navidrome/navidrome@8c80be56d) by [@deluan](https://github.com/deluan))
  - Fix "Expression tree is too large" error by executing GetFolderUpdateInfo in batches. ([cde5992](navidrome/navidrome@cde5992c4) by [@deluan](https://github.com/deluan))
  - Fix stale role associations when artist role changes. ([2d7b716](navidrome/navidrome@2d7b71683) by [@deluan](https://github.com/deluan))
  - Fix infinite recursion in PID configuration. ([1c4a7e8](navidrome/navidrome@1c4a7e855) by [@deluan](https://github.com/deluan))
  - Fix default PIDs not being set for Album and Track. In some circumstances it could lead to empty PIDs ([71f549a](navidrome/navidrome@71f549afb) by [@deluan](https://github.com/deluan))
  - Fix error when watcher detected too many folder changes, causing the scan to fail. ([9ed309a](navidrome/navidrome@9ed309ac8) by [@deluan](https://github.com/deluan))
  - Show scan errors in the UI more consistently. ([ebbc31f](navidrome/navidrome@ebbc31f1a) by [@deluan](https://github.com/deluan))

- Subsonic API:
  - Fix username parameter validation for `getUser` endpoint. ([6ed6524](navidrome/navidrome@6ed652475) by [@deluan](https://github.com/deluan))
  - Fix `getNowPlaying` endpoint to always be enabled regardless of configuration. ([603cccd](navidrome/navidrome@603cccde1) by [@deluan](https://github.com/deluan))

- Server:
  - Fix JWT-related errors being exposed on share page. ([#4892](navidrome/navidrome#4892) by [@AlexGustafsson](https://github.com/AlexGustafsson))
  - Fix user context not preserved in async NowPlaying dispatch. ([396eee4](navidrome/navidrome@396eee48c) by [@deluan](https://github.com/deluan))
  - Fix environment variable configuration loading not being logged when no config file is found. ([51ca2de](navidrome/navidrome@51ca2dee6) by [@deluan](https://github.com/deluan))
  - Fix items with no annotation not being included for `starred=false` filter, handle `has_rating=false`. ([#4921](navidrome/navidrome#4921) by [@kgarner7](https://github.com/kgarner7))
  - Last.fm's `scrobble` and `updateNowPlaying` methods should send parameters in request body. ([51026de](navidrome/navidrome@51026de80) by [@deluan](https://github.com/deluan))

##### New Contributors

- [@alannnna](https://github.com/alannnna) made their first contribution in [#4899](navidrome/navidrome#4899)
- [@abrugues](https://github.com/abrugues) made their first contribution in [#4904](navidrome/navidrome#4904)
- [@AlexGustafsson](https://github.com/AlexGustafsson) made their first contribution in [#4857](navidrome/navidrome#4857)
- [@borisrorsvort](https://github.com/borisrorsvort) made their first contribution in [#4909](navidrome/navidrome#4909)
- [@dragonish](https://github.com/dragonish) made their first contribution in [#4797](navidrome/navidrome#4797)
- [@MichaIng](https://github.com/MichaIng) made their first contribution in [#4949](navidrome/navidrome#4949)
- [@terry90](https://github.com/terry90) made their first contribution in [#4900](navidrome/navidrome#4900)
- [@typhoon2099](https://github.com/typhoon2099) made their first contribution in [#4850](navidrome/navidrome#4850)

**Full Changelog**: <navidrome/navidrome@v0.59.0...v0.60.0>

##### Helping out

This release is only possible thanks to the support of some **awesome people**!

Want to be one of them?
You can [sponsor](https://github.com/sponsors/deluan), pay me a [Ko-fi](https://ko-fi.com/deluan), or [contribute with code](https://www.navidrome.org/docs/developers/).

##### Where to go next?

- Read installation instructions on our [website](https://www.navidrome.org/docs/installation/).
- Host Navidrome on [PikaPods](https://www.pikapods.com/pods/navidrome) for a simple cloud solution.
- Reach out on [Discord](https://discord.gg/xh7j7yF), [Reddit](https://www.reddit.com/r/navidrome/) and [Twitter](https://twitter.com/navidrome)!
renovate bot added a commit to sdwilsh/ansible-playbooks that referenced this pull request Feb 9, 2026
##### [\`0.60.0\`](https://github.com/navidrome/navidrome/releases/tag/v0.60.0)

##### Plugins

This release introduces a major rewrite of the experimental **Plugin System**, now with multi-language PDK support, enabling developers to extend Navidrome's functionality using WebAssembly-based plugins written in Go, Rust, Python or JavaScript. Plugins run in a secure sandbox and can provide additional metadata sources, custom integrations, and server-side enhancements. Users can now easily configure plugins directly from the UI through a new JSONForms-based configuration interface.

A couple of working plugins are already available:

- [AudioMuse-AI integration](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin)
- [ListenBrainz Daily Playlist Importer](https://github.com/kgarner7/navidrome-listenbrainz-daily-playlist)
- [Discord Rich Presence](https://github.com/navidrome/discord-rich-presence-plugin)

For more plugins, keep an eye on the tag [navidrome-plugins](https://github.com/topics/navidrome-plugin) in GitHub.

More details and instructions on how to use and manage plugins can be found in our [documentation](https://www.navidrome.org/docs/usage/features/plugins/).
New documentation will soon be added with details on how to create new plugins.

##### Metadata Extraction

Additionally, this version includes a **pure-Go metadata extractor** built on top of the new `go-taglib` library. This is a significant step toward removing the C++ TagLib dependency, which will simplify cross-platform builds and packaging in future releases. The new extractor is activated by default, but in case of any issues you can revert to the previous implementation by setting `Scanner.Extractor="legacy-taglib"` configuration option.

##### Instant Mix

The Instant Mix feature generates a playlist of similar songs based on a selected track. By default, it retrieves similar songs from Last.fm (if configured with an API key) or falls back to Deezer. It can also be configured to use external plugins, like [AudioMuse-AI](https://github.com/NeptuneHub/AudioMuse-AI-NV-plugin) for sonic analysis-based similarity recommendations.

##### New and Changed Configuration Options

##### Plugin System Options

| Option               | Default   | Description                                                   |
| -------------------- | --------- | ------------------------------------------------------------- |
| `Plugins.Enabled`    | `true`    | Enable/disable the plugin system                              |
| `Plugins.Folder`     | `""`      | Path to the plugins directory. Default: `$DataFolder/Plugins` |
| `Plugins.CacheSize`  | `"200MB"` | Maximum cache size for storing compiled plugin WASM modules   |
| `Plugins.AutoReload` | `false`   | Automatically detect new/changed/removed plugins              |
| `Plugins.LogLevel`   | `""`      | Override log level for plugin-related messages                |

##### Subsonic API Options

| Option                         | Default | Description                                                                                                                    |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Subsonic.MinimalClients`      | `""`    | Comma-separated list of clients that receive reduced API responses (useful for resource-constrained devices like smartwatches) |
| `Subsonic.EnableAverageRating` | `true`  | Include average rating in API responses                                                                                        |

##### Metadata & Matching Options

| Option                       | Default | Description                                                                                        |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `SimilarSongsMatchThreshold` | `85`    | Minimum similarity score (0-100) for matching similar songs from external sources to local library |
| `LastFM.Language`            | `"en"`  | Now supports comma-separated list of languages (e.g., `"de,fr,en"`) for metadata fallback          |
| `Deezer.Language`            | `"en"`  | Now supports comma-separated list of languages for metadata fallback                               |

##### Renamed Options (Deprecation Notice)

The following options have been renamed. The old names still work but will be removed in a future release:

| Old Name                                      | New Name                   |
| --------------------------------------------- | -------------------------- |
| `HTTPSecurityHeaders.CustomFrameOptionsValue` | `HTTPHeaders.FrameOptions` |

##### Security

- Fix potential XSS vulnerability by sanitizing user-supplied data before rendering ([GHSA-rh3r-8pxm-hg4w](GHSA-rh3r-8pxm-hg4w)). ([d7ec735](navidrome/navidrome@d7ec7355c) by [@AlexGustafsson](https://github.com/AlexGustafsson))
- Fix potential DoS vulnerability in cover art upscaling by clamping requested square size to original dimensions ([GHSA-hrr4-3wgr-68x3](GHSA-hrr4-3wgr-68x3)). ([77367548](navidrome/navidrome@77367548f) by [@deluan](https://github.com/deluan)). Thanks to [@yunfachi](https://github.com/yunfachi)

##### Added

- Plugins:
  - Add new WebAssembly-based plugin system with multi-language PDK support (Go, Rust, Python). ([#4833](navidrome/navidrome#4833) by [@deluan](https://github.com/deluan))
  - Add JSONForms-based plugin configuration UI. ([#4911](navidrome/navidrome#4911) by [@deluan](https://github.com/deluan))
  - Add similar songs retrieval functions to plugins API. ([#4933](navidrome/navidrome#4933) by [@deluan](https://github.com/deluan))

- Server:
  - Add pure-Go metadata extractor (`go-taglib`) as alternative to FFmpeg-based extraction. ([#4902](navidrome/navidrome#4902) by [@deluan](https://github.com/deluan))
  - Add support for reading embedded images using the new taglib extractor by default. ([66474fc](navidrome/navidrome@66474fc9f) by [@deluan](https://github.com/deluan))
  - Add Instant Mix (song-based Similar Songs) functionality with MBID, ISRC and Title/Artist fuzzy matching. ([#4919](navidrome/navidrome#4919), [#4946](navidrome/navidrome#4946) by [@deluan](https://github.com/deluan))
  - Add support for multiple languages when fetching metadata from Last.fm and Deezer. ([#4952](navidrome/navidrome#4952) by [@deluan](https://github.com/deluan))
  - Add `Subsonic.MinimalClients` configuration option for improved compatibility with minimal Subsonic clients. Default list is `"SubMusic"` ([#4850](navidrome/navidrome#4850) by [@typhoon2099](https://github.com/typhoon2099))
  - Add support for public/private playlists in NSP import. ([c5447a6](navidrome/navidrome@c5447a637) by [@deluan](https://github.com/deluan))
  - Add RISCV64 builds. ([#4949](navidrome/navidrome#4949) by [@MichaIng](https://github.com/MichaIng))

- UI Features:
  - Add composer field to table views. ([#4857](navidrome/navidrome#4857) by [@AlexGustafsson](https://github.com/AlexGustafsson))
  - Add prompt before closing window if music is playing. ([#4899](navidrome/navidrome#4899) by [@alannnna](https://github.com/alannnna))
  - Add Nautiline-like theme. ([#4909](navidrome/navidrome#4909) by [@borisrorsvort](https://github.com/borisrorsvort))
  - Add multiline support and resizing for playlist comment input. ([6fce30c](navidrome/navidrome@6fce30c13) by [@deluan](https://github.com/deluan))

- Subsonic API:
  - Add `avgRating` field from Subsonic spec. ([#4900](navidrome/navidrome#4900) by [@terry90](https://github.com/terry90))

- Insights:
  - Add insights collection for Scanner.Extractor configuration to measure go-taglib usage. ([63517e9](navidrome/navidrome@63517e904) by [@deluan](https://github.com/deluan))
  - Add file suffix counting to insights. ([0473c50](navidrome/navidrome@0473c50b4) by [@deluan](https://github.com/deluan))

##### Changed

- Optimize cross-library move detection for single-library setups. ([#4888](navidrome/navidrome#4888) by [@deluan](https://github.com/deluan))
- Improve Deezer artist search ranking. ([a081569](navidrome/navidrome@a081569ed) by [@deluan](https://github.com/deluan))
- Rename `HTTPSecurityHeaders.CustomFrameOptionsValue` to `HTTPHeaders.FrameOptions`. ([7ccf44b](navidrome/navidrome@7ccf44b8e) by [@deluan](https://github.com/deluan))
- Update translations: Bulgarian, Catalan, German, Greek, Spanish, Finnish, French, Galician, Indonesian, Dutch, Polish, Russian, Slovenian, Swedish, Thai by [POEditor contributors](https://www.navidrome.org/docs/developers/translations/).
- Update Spanish translations. ([#4904](navidrome/navidrome#4904) by [@abrugues](https://github.com/abrugues))
- Update Basque translation. ([#4815](navidrome/navidrome#4815) by [@xabirequejo](https://github.com/xabirequejo))

##### Fixed

- Playlists:
  - Fix M3U playlist import failing for paths with different UTF/Unicode representations (NFC/NFD normalization). ([#4890](navidrome/navidrome#4890) by [@deluan](https://github.com/deluan))
  - Fix playlist name sorting to be case-insensitive. ([#4845](navidrome/navidrome#4845) by [@deluan](https://github.com/deluan))

- UI:
  - Fix various UI issues and improve styling coherence. ([#4910](navidrome/navidrome#4910) by [@borisrorsvort](https://github.com/borisrorsvort))
  - Fix AMusic theme player buttons and delete button color. ([#4797](navidrome/navidrome#4797) by [@dragonish](https://github.com/dragonish))
  - Fix export missing files showing only first 1000 results. ([017676c](navidrome/navidrome@017676c45) by [@deluan](https://github.com/deluan))

- Scanner:
  - Fix `FullScanInProgress` not reflecting current scan request during interrupted scans. ([8c80be5](navidrome/navidrome@8c80be56d) by [@deluan](https://github.com/deluan))
  - Fix "Expression tree is too large" error by executing GetFolderUpdateInfo in batches. ([cde5992](navidrome/navidrome@cde5992c4) by [@deluan](https://github.com/deluan))
  - Fix stale role associations when artist role changes. ([2d7b716](navidrome/navidrome@2d7b71683) by [@deluan](https://github.com/deluan))
  - Fix infinite recursion in PID configuration. ([1c4a7e8](navidrome/navidrome@1c4a7e855) by [@deluan](https://github.com/deluan))
  - Fix default PIDs not being set for Album and Track. In some circumstances it could lead to empty PIDs ([71f549a](navidrome/navidrome@71f549afb) by [@deluan](https://github.com/deluan))
  - Fix error when watcher detected too many folder changes, causing the scan to fail. ([9ed309a](navidrome/navidrome@9ed309ac8) by [@deluan](https://github.com/deluan))
  - Show scan errors in the UI more consistently. ([ebbc31f](navidrome/navidrome@ebbc31f1a) by [@deluan](https://github.com/deluan))

- Subsonic API:
  - Fix username parameter validation for `getUser` endpoint. ([6ed6524](navidrome/navidrome@6ed652475) by [@deluan](https://github.com/deluan))
  - Fix `getNowPlaying` endpoint to always be enabled regardless of configuration. ([603cccd](navidrome/navidrome@603cccde1) by [@deluan](https://github.com/deluan))

- Server:
  - Fix JWT-related errors being exposed on share page. ([#4892](navidrome/navidrome#4892) by [@AlexGustafsson](https://github.com/AlexGustafsson))
  - Fix user context not preserved in async NowPlaying dispatch. ([396eee4](navidrome/navidrome@396eee48c) by [@deluan](https://github.com/deluan))
  - Fix environment variable configuration loading not being logged when no config file is found. ([51ca2de](navidrome/navidrome@51ca2dee6) by [@deluan](https://github.com/deluan))
  - Fix items with no annotation not being included for `starred=false` filter, handle `has_rating=false`. ([#4921](navidrome/navidrome#4921) by [@kgarner7](https://github.com/kgarner7))
  - Last.fm's `scrobble` and `updateNowPlaying` methods should send parameters in request body. ([51026de](navidrome/navidrome@51026de80) by [@deluan](https://github.com/deluan))

##### New Contributors

- [@alannnna](https://github.com/alannnna) made their first contribution in [#4899](navidrome/navidrome#4899)
- [@abrugues](https://github.com/abrugues) made their first contribution in [#4904](navidrome/navidrome#4904)
- [@AlexGustafsson](https://github.com/AlexGustafsson) made their first contribution in [#4857](navidrome/navidrome#4857)
- [@borisrorsvort](https://github.com/borisrorsvort) made their first contribution in [#4909](navidrome/navidrome#4909)
- [@dragonish](https://github.com/dragonish) made their first contribution in [#4797](navidrome/navidrome#4797)
- [@MichaIng](https://github.com/MichaIng) made their first contribution in [#4949](navidrome/navidrome#4949)
- [@terry90](https://github.com/terry90) made their first contribution in [#4900](navidrome/navidrome#4900)
- [@typhoon2099](https://github.com/typhoon2099) made their first contribution in [#4850](navidrome/navidrome#4850)

**Full Changelog**: <navidrome/navidrome@v0.59.0...v0.60.0>

##### Helping out

This release is only possible thanks to the support of some **awesome people**!

Want to be one of them?
You can [sponsor](https://github.com/sponsors/deluan), pay me a [Ko-fi](https://ko-fi.com/deluan), or [contribute with code](https://www.navidrome.org/docs/developers/).

##### Where to go next?

- Read installation instructions on our [website](https://www.navidrome.org/docs/installation/).
- Host Navidrome on [PikaPods](https://www.pikapods.com/pods/navidrome) for a simple cloud solution.
- Reach out on [Discord](https://discord.gg/xh7j7yF), [Reddit](https://www.reddit.com/r/navidrome/) and [Twitter](https://twitter.com/navidrome)!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants