Pārlūkot izejas kodu

Backport pull request #11859 from jellyfin/release-10.9.z

Use music metadata from ffprobe when TagLib fails

Original-merge: b8a0cf6a9e627c3137700b71d3e52e6e11f8d96b

Merged-by: crobibero <cody@robibe.ro>

Backported-by: Joshua M. Boniface <joshua@boniface.me>
gnattu 1 gadu atpakaļ
vecāks
revīzija
2599babe31
1 mainītis faili ar 161 papildinājumiem un 146 dzēšanām
  1. 161 146
      MediaBrowser.Providers/MediaInfo/AudioFileProber.cs

+ 161 - 146
MediaBrowser.Providers/MediaInfo/AudioFileProber.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
@@ -151,198 +152,212 @@ namespace MediaBrowser.Providers.MediaInfo
         /// <param name="tryExtractEmbeddedLyrics">Whether to extract embedded lyrics to lrc file. </param>
         private async Task FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo mediaInfo, MetadataRefreshOptions options, bool tryExtractEmbeddedLyrics)
         {
-            using var file = TagLib.File.Create(audio.Path);
-            var tagTypes = file.TagTypesOnDisk;
             Tag? tags = null;
-
-            if (tagTypes.HasFlag(TagTypes.Id3v2))
-            {
-                tags = file.GetTag(TagTypes.Id3v2);
-            }
-            else if (tagTypes.HasFlag(TagTypes.Ape))
-            {
-                tags = file.GetTag(TagTypes.Ape);
-            }
-            else if (tagTypes.HasFlag(TagTypes.FlacMetadata))
-            {
-                tags = file.GetTag(TagTypes.FlacMetadata);
-            }
-            else if (tagTypes.HasFlag(TagTypes.Apple))
+            try
             {
-                tags = file.GetTag(TagTypes.Apple);
-            }
-            else if (tagTypes.HasFlag(TagTypes.Xiph))
-            {
-                tags = file.GetTag(TagTypes.Xiph);
-            }
-            else if (tagTypes.HasFlag(TagTypes.AudibleMetadata))
-            {
-                tags = file.GetTag(TagTypes.AudibleMetadata);
+                using var file = TagLib.File.Create(audio.Path);
+                var tagTypes = file.TagTypesOnDisk;
+
+                if (tagTypes.HasFlag(TagTypes.Id3v2))
+                {
+                    tags = file.GetTag(TagTypes.Id3v2);
+                }
+                else if (tagTypes.HasFlag(TagTypes.Ape))
+                {
+                    tags = file.GetTag(TagTypes.Ape);
+                }
+                else if (tagTypes.HasFlag(TagTypes.FlacMetadata))
+                {
+                    tags = file.GetTag(TagTypes.FlacMetadata);
+                }
+                else if (tagTypes.HasFlag(TagTypes.Apple))
+                {
+                    tags = file.GetTag(TagTypes.Apple);
+                }
+                else if (tagTypes.HasFlag(TagTypes.Xiph))
+                {
+                    tags = file.GetTag(TagTypes.Xiph);
+                }
+                else if (tagTypes.HasFlag(TagTypes.AudibleMetadata))
+                {
+                    tags = file.GetTag(TagTypes.AudibleMetadata);
+                }
+                else if (tagTypes.HasFlag(TagTypes.Id3v1))
+                {
+                    tags = file.GetTag(TagTypes.Id3v1);
+                }
             }
-            else if (tagTypes.HasFlag(TagTypes.Id3v1))
+            catch (Exception e)
             {
-                tags = file.GetTag(TagTypes.Id3v1);
+                _logger.LogWarning(e, "TagLib-Sharp does not support this audio");
             }
 
-            if (tags is not null)
+            tags ??= new TagLib.Id3v2.Tag();
+            tags.AlbumArtists ??= mediaInfo.AlbumArtists;
+            tags.Album ??= mediaInfo.Album;
+            tags.Title ??= mediaInfo.Name;
+            tags.Year = tags.Year == 0U ? Convert.ToUInt32(mediaInfo.ProductionYear, CultureInfo.InvariantCulture) : tags.Year;
+            tags.Performers ??= mediaInfo.Artists;
+            tags.Genres ??= mediaInfo.Genres;
+            tags.Track = tags.Track == 0U ? Convert.ToUInt32(mediaInfo.IndexNumber, CultureInfo.InvariantCulture) : tags.Track;
+            tags.Disc = tags.Disc == 0U ? Convert.ToUInt32(mediaInfo.ParentIndexNumber, CultureInfo.InvariantCulture) : tags.Disc;
+
+            if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast))
             {
-                if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast))
+                var people = new List<PersonInfo>();
+                var albumArtists = tags.AlbumArtists;
+                foreach (var albumArtist in albumArtists)
                 {
-                    var people = new List<PersonInfo>();
-                    var albumArtists = tags.AlbumArtists;
-                    foreach (var albumArtist in albumArtists)
+                    if (!string.IsNullOrEmpty(albumArtist))
                     {
-                        if (!string.IsNullOrEmpty(albumArtist))
+                        PeopleHelper.AddPerson(people, new PersonInfo
                         {
-                            PeopleHelper.AddPerson(people, new PersonInfo
-                            {
-                                Name = albumArtist,
-                                Type = PersonKind.AlbumArtist
-                            });
-                        }
+                            Name = albumArtist,
+                            Type = PersonKind.AlbumArtist
+                        });
                     }
+                }
 
-                    var performers = tags.Performers;
-                    foreach (var performer in performers)
+                var performers = tags.Performers;
+                foreach (var performer in performers)
+                {
+                    if (!string.IsNullOrEmpty(performer))
                     {
-                        if (!string.IsNullOrEmpty(performer))
+                        PeopleHelper.AddPerson(people, new PersonInfo
                         {
-                            PeopleHelper.AddPerson(people, new PersonInfo
-                            {
-                                Name = performer,
-                                Type = PersonKind.Artist
-                            });
-                        }
+                            Name = performer,
+                            Type = PersonKind.Artist
+                        });
                     }
+                }
 
-                    foreach (var composer in tags.Composers)
+                foreach (var composer in tags.Composers)
+                {
+                    if (!string.IsNullOrEmpty(composer))
                     {
-                        if (!string.IsNullOrEmpty(composer))
+                        PeopleHelper.AddPerson(people, new PersonInfo
                         {
-                            PeopleHelper.AddPerson(people, new PersonInfo
-                            {
-                                Name = composer,
-                                Type = PersonKind.Composer
-                            });
-                        }
-                    }
-
-                    _libraryManager.UpdatePeople(audio, people);
-
-                    if (options.ReplaceAllMetadata && performers.Length != 0)
-                    {
-                        audio.Artists = performers;
-                    }
-                    else if (!options.ReplaceAllMetadata
-                             && (audio.Artists is null || audio.Artists.Count == 0))
-                    {
-                        audio.Artists = performers;
-                    }
-
-                    if (albumArtists.Length == 0)
-                    {
-                        // Album artists not provided, fall back to performers (artists).
-                        albumArtists = performers;
-                    }
-
-                    if (options.ReplaceAllMetadata && albumArtists.Length != 0)
-                    {
-                        audio.AlbumArtists = albumArtists;
-                    }
-                    else if (!options.ReplaceAllMetadata
-                             && (audio.AlbumArtists is null || audio.AlbumArtists.Count == 0))
-                    {
-                        audio.AlbumArtists = albumArtists;
+                            Name = composer,
+                            Type = PersonKind.Composer
+                        });
                     }
                 }
 
-                if (!audio.LockedFields.Contains(MetadataField.Name) && !string.IsNullOrEmpty(tags.Title))
-                {
-                    audio.Name = tags.Title;
-                }
+                _libraryManager.UpdatePeople(audio, people);
 
-                if (options.ReplaceAllMetadata)
+                if (options.ReplaceAllMetadata && performers.Length != 0)
                 {
-                    audio.Album = tags.Album;
-                    audio.IndexNumber = Convert.ToInt32(tags.Track);
-                    audio.ParentIndexNumber = Convert.ToInt32(tags.Disc);
+                    audio.Artists = performers;
                 }
-                else
+                else if (!options.ReplaceAllMetadata
+                         && (audio.Artists is null || audio.Artists.Count == 0))
                 {
-                    audio.Album ??= tags.Album;
-                    audio.IndexNumber ??= Convert.ToInt32(tags.Track);
-                    audio.ParentIndexNumber ??= Convert.ToInt32(tags.Disc);
+                    audio.Artists = performers;
                 }
 
-                if (tags.Year != 0)
+                if (albumArtists.Length == 0)
                 {
-                    var year = Convert.ToInt32(tags.Year);
-                    audio.ProductionYear = year;
-
-                    if (!audio.PremiereDate.HasValue)
-                    {
-                        try
-                        {
-                            audio.PremiereDate = new DateTime(year, 01, 01);
-                        }
-                        catch (ArgumentOutOfRangeException ex)
-                        {
-                            _logger.LogError(ex, "Error parsing YEAR tag in {File}. '{TagValue}' is an invalid year.", audio.Path, tags.Year);
-                        }
-                    }
+                    // Album artists not provided, fall back to performers (artists).
+                    albumArtists = performers;
                 }
 
-                if (!audio.LockedFields.Contains(MetadataField.Genres))
+                if (options.ReplaceAllMetadata && albumArtists.Length != 0)
                 {
-                    audio.Genres = options.ReplaceAllMetadata || audio.Genres == null || audio.Genres.Length == 0
-                        ? tags.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray()
-                        : audio.Genres;
+                    audio.AlbumArtists = albumArtists;
                 }
-
-                if (!double.IsNaN(tags.ReplayGainTrackGain))
+                else if (!options.ReplaceAllMetadata
+                         && (audio.AlbumArtists is null || audio.AlbumArtists.Count == 0))
                 {
-                    audio.NormalizationGain = (float)tags.ReplayGainTrackGain;
-                }
-
-                if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzArtist, out _))
-                {
-                    audio.SetProviderId(MetadataProvider.MusicBrainzArtist, tags.MusicBrainzArtistId);
+                    audio.AlbumArtists = albumArtists;
                 }
+            }
 
-                if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbumArtist, out _))
-                {
-                    audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, tags.MusicBrainzReleaseArtistId);
-                }
+            if (!audio.LockedFields.Contains(MetadataField.Name) && !string.IsNullOrEmpty(tags.Title))
+            {
+                audio.Name = tags.Title;
+            }
 
-                if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbum, out _))
-                {
-                    audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, tags.MusicBrainzReleaseId);
-                }
+            if (options.ReplaceAllMetadata)
+            {
+                audio.Album = tags.Album;
+                audio.IndexNumber = Convert.ToInt32(tags.Track);
+                audio.ParentIndexNumber = Convert.ToInt32(tags.Disc);
+            }
+            else
+            {
+                audio.Album ??= tags.Album;
+                audio.IndexNumber ??= Convert.ToInt32(tags.Track);
+                audio.ParentIndexNumber ??= Convert.ToInt32(tags.Disc);
+            }
 
-                if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzReleaseGroup, out _))
-                {
-                    audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, tags.MusicBrainzReleaseGroupId);
-                }
+            if (tags.Year != 0)
+            {
+                var year = Convert.ToInt32(tags.Year);
+                audio.ProductionYear = year;
 
-                if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzTrack, out _))
+                if (!audio.PremiereDate.HasValue)
                 {
-                    // Fallback to ffprobe as TagLib incorrectly provides recording MBID in `tags.MusicBrainzTrackId`.
-                    // See https://github.com/mono/taglib-sharp/issues/304
-                    var trackMbId = mediaInfo.GetProviderId(MetadataProvider.MusicBrainzTrack);
-                    if (trackMbId is not null)
+                    try
                     {
-                        audio.SetProviderId(MetadataProvider.MusicBrainzTrack, trackMbId);
+                        audio.PremiereDate = new DateTime(year, 01, 01);
+                    }
+                    catch (ArgumentOutOfRangeException ex)
+                    {
+                        _logger.LogError(ex, "Error parsing YEAR tag in {File}. '{TagValue}' is an invalid year", audio.Path, tags.Year);
                     }
                 }
+            }
+
+            if (!audio.LockedFields.Contains(MetadataField.Genres))
+            {
+                audio.Genres = options.ReplaceAllMetadata || audio.Genres == null || audio.Genres.Length == 0
+                    ? tags.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray()
+                    : audio.Genres;
+            }
+
+            if (!double.IsNaN(tags.ReplayGainTrackGain))
+            {
+                audio.NormalizationGain = (float)tags.ReplayGainTrackGain;
+            }
+
+            if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzArtist, out _))
+            {
+                audio.SetProviderId(MetadataProvider.MusicBrainzArtist, tags.MusicBrainzArtistId);
+            }
+
+            if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbumArtist, out _))
+            {
+                audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, tags.MusicBrainzReleaseArtistId);
+            }
+
+            if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbum, out _))
+            {
+                audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, tags.MusicBrainzReleaseId);
+            }
+
+            if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzReleaseGroup, out _))
+            {
+                audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, tags.MusicBrainzReleaseGroupId);
+            }
 
-                // Save extracted lyrics if they exist,
-                // and if the audio doesn't yet have lyrics.
-                if (!string.IsNullOrWhiteSpace(tags.Lyrics)
-                    && tryExtractEmbeddedLyrics)
+            if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzTrack, out _))
+            {
+                // Fallback to ffprobe as TagLib incorrectly provides recording MBID in `tags.MusicBrainzTrackId`.
+                // See https://github.com/mono/taglib-sharp/issues/304
+                var trackMbId = mediaInfo.GetProviderId(MetadataProvider.MusicBrainzTrack);
+                if (trackMbId is not null)
                 {
-                    await _lyricManager.SaveLyricAsync(audio, "lrc", tags.Lyrics).ConfigureAwait(false);
+                    audio.SetProviderId(MetadataProvider.MusicBrainzTrack, trackMbId);
                 }
             }
+
+            // Save extracted lyrics if they exist,
+            // and if the audio doesn't yet have lyrics.
+            if (!string.IsNullOrWhiteSpace(tags.Lyrics)
+                && tryExtractEmbeddedLyrics)
+            {
+                await _lyricManager.SaveLyricAsync(audio, "lrc", tags.Lyrics).ConfigureAwait(false);
+            }
         }
 
         private void AddExternalLyrics(