navidrome / navidrome

🎧☁️ Modern Music Server and Streamer compatible with Subsonic/Airsonic
https://www.navidrome.org
GNU General Public License v3.0
10.36k stars 797 forks source link

Support multiple artists, with custom separator #238

Open nebula-it opened 4 years ago

nebula-it commented 4 years ago

As discussed here it would be a good idea to implement a setting where end user can select a custom character that will be used to split multiple artist into separate values.

Current Behavior

A song has Contributing Artist value Artist1, Artist2. Navidrome reads the artist as a single value with name "Artist1, Artist2"

Expected Behavior

A song has Contributing Artist value Artist1, Artist2. Navidrome reads the artist and recognizes there are two or multiple artists separated by comma and song show up under the Artist page of Artist1 and Artist2. The separator character can be selected (comma in the above example) by end user depending on how their library is tagged.

deluan commented 4 years ago

Thanks, I will try to work on this after #211

JaneX8 commented 4 years ago

I would like to see this available for multiple custom seperators, not limited to one or several single characters. For uses such as " feat. ", " featuring ", " vs ", " vs." and " versus " and possible " & ", " and ". All should be case insensitive (or optional) and after separation the values should be trimmed.

Maybe we can allow regular expressions for separation? Keep in mind that introduces some possible security implications like ReDoS.

deluan commented 4 years ago

Yes, the idea is to allow multiple words as separators. Not sure if Regex is any good here (and have the security implications as you said)

certuna commented 4 years ago

Bear in mind that there is a standard separator: / for id3v2.3, and the null character (0x00) for id3v2.4. Vorbis Comments (used for FLAC) just has multiple ARTIST tags. Other separators like ;,& are technically nonstandard hacks.

The fancier the separators are, the more chance of false positives. Some examples that get split accidentally:

Interesting discussions: https://hydrogenaud.io/index.php?topic=112634.0 https://emby.media/community/index.php?/topic/5731-question-on-music-tags-and-delimiters/ https://community.mp3tag.de/t/multiple-genres-in-1-genre-tag/17159

deluan commented 3 years ago

ffmpeg (used to extract the tags) does not support id3v2.4 multi-valued tags: https://trac.ffmpeg.org/ticket/6949. I just tested with the latest version and it basically ignore everything after the null separator....

To make this work, I'll need to find an alternative way to read tags (at least id3 tags, have to test with vorbis and mp4), that is robust enough and does not add extra dependencies to the project....

certuna commented 3 years ago

That is pretty terrible actually - three years and still not fixed?

certuna commented 3 years ago

By the looks of it, the ffmpeg devs don't care, so the solution is either find another tag library or write a commit for ffmpeg (how's your C?) - what's the least amount of work?

deluan commented 3 years ago

Both options are huge tasks (for my limited time). I tried replacing ffmpeg before, but could not find a library that would cover all formats and all required info I need from the files (including duration and bitrate). I also use https://github.com/dhowden/tag to extract pictures (and it gets null-separated multi-valued fields correctly), but it does not provide all info required.

I'll take a look in the ffmpeg codebase, but I don't anticipate a easy change to fix this...

certuna commented 3 years ago

So taglib is our new saviour?

deluan commented 3 years ago

@certuna I'm still evaluating it, but it seems to be a better option for extracting metadata. Some of the bugs/annoyances we have with ffmpeg don't exist with taglib. I'm doing more tests with it this week

certuna commented 3 years ago

Is there any reason why there still seems to be (reasonably) recent commits but no releases since 2016?

certuna commented 3 years ago

By the way, I see that Picard has introduced a custom tag for "artists" (TXXX:Artists in id3, ARTISTS in Vorbis) to store multivalued artists, presumably so old/noncompliant players don't choke on multivalued fields in the regular "artist" fields TPE1 and ARTIST . An ugly hack I think, but probably worth including this frame when multivalued fields are implemented.

orlea commented 2 years ago

Will this feature be added in the future?

deluan commented 2 years ago

Yes, definitely. Probably next after some big PRs are merged and I finish Smart playlists

krateng commented 2 years ago

In the meantime, while Navidrome can only accept one artist, is there something that could be done about the multiple artist tags in Vorbis comments (flac)? If I have a track with

ARTIST=K/DA
ARTIST=Seraphine

it only shows one of them - would be nice to simply display that as K/DA;Seraphine for the purpose of scrobbling.

certuna commented 2 years ago

That's a good idea - I'll have a look how hard it is to implement that. BTW this can only be done when using TagLib as a scanner, since ffmpeg will never read the second value.

I have been thinking whether it makes sense to treat album artists and track artists differently: Abum Artists, reduce "Artist1;Artist2" to "Artist1", Track Artist, store as "Artist1;Artist2". But this is probably confusing for users and also not how a lot of people would want it.

All this is temporary anyway, until Navidrome supports multiple artists.

Baswazz commented 2 years ago

I see LMS is supporting \\ as a separator. This could be an idea also supported with multiple genres.

Artist1\\Artist2

irdkwmnsb commented 1 year ago

Any progress on this feature?

KucharczykL commented 1 year ago

Seems this will be fixed in ffmpeg itself according to the latest comments in http://trac.ffmpeg.org/ticket/6949

jmbannon commented 1 year ago

id3v2.4 using albumartists should be the way multiple artists is implemented, not separators

certuna commented 1 year ago

the custom tag fields artists and albumartists are a pretty messy hack for applications that cannot read multivalued tags correctly, it's probably better to just implement multivalued tags outright.

But once multivalued artists are implemented, it's relatively easy to add support for it - just on scan, do: if artists frame exists, then include the values in that frame

tam481 commented 1 year ago

This will also help with multilingual tagging where the artist name can be in the native language and perhaps the "ARTISTSORT" tag can be used for the English version of the name etc

Xarishark commented 1 year ago

Streaming services have made the best version of this right now. On Deezer the album/song appears on both artists pages and where the artists info is it displays both artists as separate clickable links to go to their artist page. Navidrome currently does not even SHOW that there is a second artists let alone let you click him etc.

certuna commented 11 months ago

The advantage that Spotify/Deezer/Tidal have is that they can control the exact formatting of the tags, which is a luxury we don't have. Also, they likely have implemented M2M relations in their underlying DB, which Navidrome doesn't have (yet).

There are basically three main ways that multiple artists are tagged these days:

  1. multi-value like the standard prescribes, so in id3v2.4: TPE1 = "Alice(null)Bob", or in FLAC/Vorbis with: ARTIST = "Alice" and ARTIST = "Bob"
  2. single-value with a non-standard separator, usually semicolon: TPE1 = "Alice;Bob" . The trick here is to avoid using separators that are too often used in artist names: "AC/DC" or "Earth, Wind & Fire" should clearly not be split.
  3. using two tags, one single-value and one multi-value: TPE1 = "Alice feat. Bob" and TXXX:ARTISTS = "Alice(null)Bob". It may seem a bit hacky to use two tags to do the work of one, but this is how MusicBrainz Picard auto-tags by default

All three methods would have to be supported.

I now have an experimental build running with multiple artist support (all three variants), see screenshot below. However, due to the current DB/API limitations, the links in the UI only take you to the first artist. But it's a lot better than nothing. Search does work over all artists, and the album will show up in the artist details pages of both Jay-Z and Kanye West (and also Frank Ocean, Beyoncé, etc).

Screenshot 2023-06-16 at 14 08 49

jmbannon commented 11 months ago

Looks awesome @certuna For any beets users, I have a PR up for multi-tag support: https://github.com/beetbox/beets/pull/4743

certuna commented 11 months ago

One of the tricky things of the two-tags approach is the edge case ARTIST = "Alice;Bob" and ARTISTS = "Carol", "Dave" - what should the application use?

jmbannon commented 11 months ago

I thought ARTIST and ALBUMARTIST typically included the join phrase, i.e. "Alice featuring Bob", "Alice, Bob", "Alice ft. Bob", etc. The app should use ARTISTS since it's more uniform. ARTIST should be treated more-so as the display artist

jmbannon commented 11 months ago

But then again not everyone will have multi-tags, so maybe use ARTIST as a fall-back

certuna commented 11 months ago

Exactly, but this assumes ARTIST has consistency with ARTISTS, which may be true for collections fully managed with autotaggers like Picard/beets, but otherwise not guaranteed, for example when someone has manually fixed tags.

In my experimental branch, ARTISTS is only used when both of the following are true:

pjadeslandes commented 11 months ago

I would like to see this available for multiple custom seperators, not limited to one or several single characters. For uses such as " feat. ", " featuring ", " vs ", " vs." and " versus " and possible " & ", " and ". All should be case insensitive (or optional) and after separation the values should be trimmed.

Maybe we can allow regular expressions for separation? Keep in mind that introduces some possible security implications like ReDoS.

I know this is super old, but I'm investigating Navidrome because I have exactly this request.

I'm aware of some of the edge cases that exist, but I always imagine there are ways around them.

For example, "AC/DC" is a continuous string with no spaces, so if using / as a delimiter, put spaces around it.

Also the use of & - to me, that's used to separate different artists, while "and" is not. Eg "Marina and The Diamonds" is one artist, while "Beyoncé & Lady Gaga" is two. And so if I want, I can treat "Prince and The Revolution" as one artist or, better for me, as two by changing the tag to "Prince & The Revolution", not because I need to see The Revolution as an artists, but I'll take that if it means that all of Prince's music is in one place, whether he was with one of his bands or not.

One slight tweak to the request: I'd like to pull artists from the track name using a format like " (feat , , etc)".

Am following the main thread on all the most recent updates. Amazing work by all involved, however far all of this gets. Such a shame commercial players like Plex aren't as dedicated to as high a quality of experience. V happy to pay / donate to something like the Navidrome prject, which is so responsive to such specific user requests.

certuna commented 11 months ago

Splitting text strings reliably is very hard, this is why the ARTIST/ARTISTS tagging method is used by for example Picard: ARTIST = "Alice featuring Bob", ARTISTS = "Alice", "Bob". This is a workaround so applications that can handle multiple artists use what's in the ARTISTS tag without having to do complex splitting operations, while oldschool applications that can only handle one artist (Plex, Apple Music etc) use the contents of ARTIST.

I'm now experimenting with splitting on phrases like "feat." and "vs.", only if there's no ARTISTS tag. So far this works quite well, but even a phrase like "vs." can throw up annoying edge cases like "Angels vs. Animals", etc. Not to mention that this is a very Anglo-centric approach: characters like & are fairly universal, but it's almost impossible to capture all join phrases like "featuring" in 120+ languages.

jmbannon commented 11 months ago

My two cents, if ARTIST was possible to reliably split on, there would be no need for ARTISTS. There will always be an edge case, which is why self hosted music should embrace the ARTISTS + ALBUMARTISTS multi-tags. I guarantee Spotify, Deezer, etc use something very similar to ARTISTS in the form of a database.

certuna commented 11 months ago

My two cents, if ARTIST was possible to reliably split on, there would be no need for ARTISTS.

Absolutely true - and ARTIST can be reliably split, the standards (id3, Vorbis, mp4) explicitly tell us how: null-separated strings (id3v2.4) or multiple ARTIST frames (Vorbis, mp4). However, over the past 25 years, users & application developers have ignored the standards, so here were are: trying to unpack other people's workarounds.

I guarantee Spotify, Deezer, etc use something very similar to ARTISTS in the form of a database.

Yeah, but these guys have full control over what goes in, they can just implement M2M relations in the DB, and ignore the millions of songs that the general public has tagged, out there in the wild. This is a luxury that self-hosted music servers don't have. Refactoring the Navidrome database would help with the multiple-artist functionality (hoping that deluan has some time for this somewhere after the UI migration), but we still have the problem of parsing what people have tagged, in a reliable/predictable manner.

jmbannon commented 11 months ago

Supporting multiple artists for folks who don't have multi-tags, to put it bluntly, is not feasible, and trying to do so I think contributes to the problem of self-hosted music's messy standard for supporting multiple artists that we see today.

The software that I use that does support multiple artists (Kodi, Jellyfin, MusicBee) treats ARTIST/ALBUMARTIST as the display artist containing the join phrases (ft. featuring, with, etc) without trying to be split on, and ARTISTS/ALBUMARTISTS to use strictly for multiple artists. This is the closest standard I've seen that I think should be adopted abroad and in your approach. There is plenty of available software (MusicBrainz Picard currently the best, beets very soon with https://github.com/beetbox/beets/pull/4743) that can add these multi-tags.

Only using multi-tags for multiple artist support will both simplify your PR and help cement this standard. I think it's okay to leave behind folks who refuse to add multi-tags.

(sorry if this comes off as brash, I just want the world to use multi-tags and enjoy multiple artist support like I do :P )

certuna commented 11 months ago

It's not so bad.

pjadeslandes commented 11 months ago

I was only thinking of these delimiters as optional characters, I'm aware something like "&" won't work for everyone but I know it would work for me. I'm all for using tags such as ARTISTS, although I use mp3Tag and I don't see it there so I guess I'd have to move apps, which won't kill me! As ever, I'm impressed by how engaged everyone here is and am very appreciative of the work done by @certuna and all other contributors.

jmbannon commented 11 months ago

@pjadeslandes I think it's under extended tags

certuna commented 11 months ago

BTW I'm just discovering that Musicbrainz Picard by default writes ARTIST (single) + ARTISTS (multi), but not like you'd expect ALBUMARTIST + ALBUMARTISTS - it just drops any additional album artists and writes ALBUMARTIST as a single field. But then Picard does write multiple artist IDs to the MBZ Release Artist ID field...so as usual with non-standard stuff, sloppy implementations everywhere.

jmbannon commented 11 months ago

They have it but you have to enable it manually. See the bottom of https://kodi.wiki/view/Music_tagging

certuna commented 11 months ago

Yeah I saw that - I've had that for testing, but it's a bit annoying for widespread adoption that it's not on by default.

certuna commented 11 months ago

The Navidrome fork I'm using for testing is now open and available for all to try, if you're interested: https://github.com/certuna/navidrome/tree/multi-artists . Still doing more testing before I submit the PR to the main Navidrome repo, but so far I see no showstoppers. Scanning speed appears to be unchanged on my 160k song library.

Four new server options (default):

Cassian-Andor commented 9 months ago

@certuna Do you trim the resulting array so that Artist1 ; Artist 2 works the same as Artist1; Artist2?

jmbannon commented 9 months ago

@certuna plz add id3v2.4 multi support for a separator type