Skip to content

Add artistRoleFilter extension#256

Open
sentriz wants to merge 3 commits into
mainfrom
feat/getartists-roles-param
Open

Add artistRoleFilter extension#256
sentriz wants to merge 3 commits into
mainfrom
feat/getartists-roles-param

Conversation

@sentriz

@sentriz sentriz commented Jul 16, 2026

Copy link
Copy Markdown
Member

getArtists (and the artist results of search3) historically return album artists only. This is the original Subsonic behavior, and legacy clients like DSub depend on it: if a server started returning track-level artists, those clients would be flooded with thousands of artists users don't care about - featured/track artists and composers dragged in from compilation albums, soundtracks, etc.

At the same time, modern OpenSubsonic clients need the opposite. A client that mirrors/syncs the whole library (e.g. Symfonium, which bulk-fetches artists via search3 with an empty query), or one that lets users browse by composer or track artist, wants all artists.

Today there's no way for a client to say which it wants - the behavior is server-defined and inconsistent across implementations:

Server getArtists returns
Airsonic (legacy Subsonic) album artists only
gonic album artists only
Navidrome album artists only
LMS configurable per-user server setting, defaults to all artists

Proposal

A new optional OpenSubsonic extension, artistRoleFilter, that lets the client choose, via a role filter:

  • getArtists: new roles parameter
  • search3: new artistRoles parameter (named to disambiguate from that endpoint's album/song results)

The value is a comma-separated list of roles matching the existing ArtistID3.roles vocabulary (albumartist, artist, composer, ...). An artist is returned if it has any of the requested roles. The special value all returns every artist regardless of role (roles are open-ended - performer, arranger, producer, subroles - so clients wanting "everyone" shouldn't have to enumerate them).

The behavior when the parameter is omitted is deliberately left to the server (historically, album artists only). This means:

  • Legacy clients are completely unaffected - nothing changes unless a client opts in.
  • Servers already returning all artists (LMS) don't have to change their default.
  • Clients that need a guarantee can request roles=albumartist or roles=all explicitly.

@netlify

netlify Bot commented Jul 16, 2026

Copy link
Copy Markdown

Deploy Preview for opensubsonic ready!

Name Link
🔨 Latest commit 45d5870
🔍 Latest deploy log https://app.netlify.com/projects/opensubsonic/deploys/6a5916955986b900089fa57d
😎 Deploy Preview https://deploy-preview-256--opensubsonic.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@sentriz sentriz changed the title Add artistRoleFilter extension Add artistRoleFilter extension Jul 16, 2026
Comment thread content/en/docs/Endpoints/getartists.md Outdated
| Parameter | Req. | OpenS. | Default | Comment |
| --- | --- | --- | --- | --- |
| `musicFolderId` | No | | | If specified, only return artists in the music folder with the given ID. See [`getMusicFolders`](../getmusicfolders). |
| `roles` | No | No / **Yes** | | A comma-separated list of roles used to filter the returned artists. Requires the [`Artist role filter`](../../extensions/artistRoleFilter/) extension. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You probably intended to have the "No / Yes" in the Req. column, not in the OpenS. column? But even there, it would probably be more correct to simply define it as "No"; the client is always allowed omit the parameter and the server should not emit an error in that case. The alert box below is IMO sufficient to indicate that the servers implementing the extension must accept the parameter.

@sentriz sentriz Jul 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hm true it is a little bit confusing, do we have the same issue in stream.md then?
image
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In the stream.md, that does make sense because the timeOffset exists already in OG Subsonic but OS extends it to be applicable on streams other than videos.

@sentriz sentriz Jul 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

nice thanks, fixed

@paulijar

Copy link
Copy Markdown
Member

To add to the table of current behavior, Nextcloud Music nowadays returns album artists only for getArtists but all artists for search3. As an exception, also getArtists returns all artists if the client is Feishin. But a cleaner solution would be very much welcome.

@Tolriq

Tolriq commented Jul 16, 2026

Copy link
Copy Markdown
Member

We need the new endpoints that handle all this and solve that.

I'll tackle that after the holidays.

@kgarner7 kgarner7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think a safer approach than comma-separated list is just repeated artistRoles=&artistRoles= (or, make it singular to save a few bytes)

One other note. artistRoles would probably also be very useful for getArtist, to specify which albums are returned for an artist. At least in Navidrome, it only returns albums where the artist is credited as an album artist (default) or artist (can be enabled). Having the role filter there will allow for fetching other album credits for this artist.

Lastly, it might be useful to have a global getAvailableRoles or similar, so a client could know which roles are available period (or, even add a per-library filter for that).

Thanks for starting this!

Comment thread content/en/docs/Endpoints/search3.md Outdated
| `songCount` | No | | 20 | Maximum number of songs to return. |
| `songOffset` | No | | 0 | Search result offset for songs. Used for paging. |
| `musicFolderId` | No | | | (Since [1.12.0](../../subsonic-versions)) Only return results from music folder with the given ID. See `getMusicFolders`. |
| `artistRoles` | No | No / **Yes** | | A comma-separated list of roles used to filter the returned artists. Requires the [`Artist role filter`](../../extensions/artistRoleFilter/) extension. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here, this should probably be Req: No, OpenS: Yes.
Also, it shouldn't be No / Yes, that means that the client is required to send it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

thanks, fixed

Comment thread content/en/docs/Endpoints/search3.md Outdated

If the server supports the [`Artist role filter`](../../extensions/artistRoleFilter/) extension, it **must** accept the `artistRoles` parameter and filter the returned **artists** accordingly (albums and songs are unaffected).

`artistRoles` is a comma-separated list of roles as found in the [`ArtistID3`](../../responses/artistid3) `roles` field (e.g. `albumartist`, `artist`, `composer`). An artist is returned if it has **any** of the requested roles. The special value `all` returns every artist regardless of role. The behavior when `artistRoles` is **not** provided is left to the server (historically, returning only album artists), so that existing clients are unaffected.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comma-separated is potentially risky (or messy) in the event one of your roles has a comma. Why not do repeated id? e.g. artistRoles=a&artistRoles=b?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need new endpoints to handle both getartists and search3, filters, sorting and telling what fields we want. Done via proper json and post as the transcoding endpoints.
This solves all the issues for all the cases and all the clients.

@deluan

deluan commented Jul 16, 2026

Copy link
Copy Markdown
Member

I think a safer approach than comma-separated list is just repeated artistRoles=&artistRoles= (or, make it singular to save a few bytes)

Yeah, I think multiple artistRole params is more aligned with Subsonic API.

One other note. artistRoles would probably also be very useful for getArtist, to specify which albums are returned for an artist. At least in Navidrome, it only returns albums where the artist is credited as an album artist (default) or artist (can be enabled). Having the role filter there will allow for fetching other album credits for this artist.

👍🏼

Lastly, it might be useful to have a global getAvailableRoles or similar, so a client could know which roles are available period (or, even add a per-library filter for that).

👍🏼

@sentriz

sentriz commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@kgarner7 @paulijar thanks! made the param singular, repeated param, and fixed the table docs

We need the new endpoints that handle all this and solve that.

I'll tackle that after the holidays.

@Tolriq oh I don't have much context on new endpoints. could be nice I suppose (though I'm not sure what problem they would solve yet)

but do you think it needs to block this? the extension is quite small (a one-line filter server-side, an extra param client-side), just additive, and unblocks what we have today: Symfonium syncing with role=all, servers keeping a lean getArtists for legacy clients. when the new endpoint lands we just deprecate it, clients lose nothing

@Tolriq

Tolriq commented Jul 16, 2026

Copy link
Copy Markdown
Member

Yes it needs to block, because it's a breaking change.

It force LMS to change it's behavior and the search3 change is breaking, if the server have the extension then it must respect it and so not passing the param should not return all artists that's breaking. Else the absence of the value despite the extension leaves the result unknown and that's against the principles of OS.

Accepting this now and having seach3 respecting the field would mean Symfonium being broken until it support this so a couple of month due to holidays ;)

Furthermore this just solve one filtering need, but there's a lot more filtering needs, so do we add an extension for each filters? What about sorting ? And what about only returning the fields that a client need to improve OS.

This was discussed quite a couple of times already about the need and the scope of the new endpoints that solve all this.

No more need for search3 and getArtists hacks and limited API a proper getLibraryArtist supporting all the needs.

I'll put a quick PR to again explain this and show some more concrete examples.

@sentriz

sentriz commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Yes it needs to block, because it's a breaking change.

It force LMS to change it's behavior and the search3 change is breaking, if the server have the extension then it must respect it and so not passing the param should not return all artists that's breaking. Else the absence of the value despite the extension leaves the result unknown and that's against the principles of OS.

Accepting this now and having seach3 respecting the field would mean Symfonium being broken until it support this so a couple of month due to holidays ;)

Furthermore this just solve one filtering need, but there's a lot more filtering needs, so do we add an extension for each filters? What about sorting ? And what about only returning the fields that a client need to improve OS.

This was discussed quite a couple of times already about the need and the scope of the new endpoints that solve all this.

No more need for search3 and getArtists hacks and limited API a proper getLibraryArtist supporting all the needs.

I'll put a quick PR to again explain this and show some more concrete examples.

Fair on scope - if we want sorting and field selection too, then yeah a proper query endpoint beats a pile of per-filter extensions. so I'll leave this one to you guys 👍

One correction though: this doesn't actually force LMS to change or break anything. no param just means whatever the server does today (LMS based on setting, gonic returns album artists), so it's purely additive. you only get a deterministic result when you opt in and pass the param. getArtists/search3 are already inconsistent across servers. this adds a deterministic path, it doesn't remove one

@deluan

deluan commented Jul 16, 2026

Copy link
Copy Markdown
Member

One correction though: this doesn't actually force LMS to change or break anything. no param just means whatever the server does today (LMS returns all, gonic returns album artists), so it's purely additive.

That's what I understand as well. Maybe making this point clear in the docs?

I'd approve this now, and it would be superseded/eclipsed by the sorting/filtering extension, whenever that is added.

@Tolriq

Tolriq commented Jul 16, 2026

Copy link
Copy Markdown
Member

We are trying to build a proper long term API, not add tons of small hacks leading to a worse API then before with clients having to jungle between different ways to do things and having to support all the different cases because server can implement just a part of it.

#258

Everything added is not temporary it's a burden for servers and clients for LIFE.

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.

5 participants