Read ALBUMARTISTS in preference to ARTISTS when PreferNonstandardArtistsTag set (#14413)

Jellyfin implemented ARTISTS multivalue tag but did not implement the equivalent ALBUMARTISTS multivalue tag.  This change adds ALBUMARTISTS support.  If present and PreferNonstandardArtistsTag is set, ALBUMARTISTS will be used in preference to ALBUMARTIST.  As with ARTISTS, the intent is to offer support for multiple album artists without affecting software that does not read ALBUMARTIST as a multivalued tag.

Example album before/after:

    ALBUM           : Amici e Rivali
    ARTIST          : Lawrence Brownlee / Michael Spyres
    album_artist    : Lawrence Brownlee
    ARTISTS         : Lawrence Brownlee;Michael Spyres
    ALBUMARTISTS    : Lawrence Brownlee;Michael Spyres

Before ALBUMARTISTS support, Jellyfin reports:
    Album Artist: Lawrence Brownlee [hyperlinked]
    On each track Artist: Lawrence Brownlee, Michael Spyres

After ALBUMARTISTS support, Jellyfin reoprts:
    Album Artist: Lawrence Brownlee [hyperlinked], Michael Spyres [hyperlinked]
    On each track Artist: none shown (no other artists in source metadata)

This is ideal as both key artists are hyperlinkable from their albums.

References to other products implementing ALBUMARTISTS:
- Navidrome: https://www.navidrome.org/docs/usage/tagging-guidelines/#handling-multiple-artists-and-collaborations
- Kodi: https://kodi.wiki/view/Music_tagging#albumartists
- MusicBrainz Picard: https://picard-docs.musicbrainz.org/en/variables/variables_basic.html (_albumartists tag)

Co-authored-by: Evan <evan@MacBook-Pro.local>
This commit is contained in:
Bond-009 2025-07-04 19:19:26 +02:00 committed by GitHub
commit 844d69ab64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -192,7 +192,20 @@ namespace MediaBrowser.Providers.MediaInfo
if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast))
{ {
var people = new List<PersonInfo>(); var people = new List<PersonInfo>();
var albumArtists = string.IsNullOrEmpty(trackAlbumArtist) ? [] : trackAlbumArtist.Split(InternalValueSeparator); string[]? albumArtists = null;
if (libraryOptions.PreferNonstandardArtistsTag)
{
TryGetSanitizedAdditionalFields(track, "ALBUMARTISTS", out var albumArtistsTagString);
if (albumArtistsTagString is not null)
{
albumArtists = albumArtistsTagString.Split(InternalValueSeparator);
}
}
if (albumArtists is null || albumArtists.Length == 0)
{
albumArtists = string.IsNullOrEmpty(trackAlbumArtist) ? [] : trackAlbumArtist.Split(InternalValueSeparator);
}
if (libraryOptions.UseCustomTagDelimiters) if (libraryOptions.UseCustomTagDelimiters)
{ {