Explorar o código

Merge pull request #5696 from Maxr1998/fix-music-video-metadata-probing

Claus Vium %!s(int64=4) %!d(string=hai) anos
pai
achega
b12f509de3

+ 56 - 39
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

@@ -124,19 +124,67 @@ namespace MediaBrowser.MediaEncoding.Probing
             {
                 info.Name = title;
             }
+            else
+            {
+                title = FFProbeHelpers.GetDictionaryValue(tags, "title-eng");
+                if (!string.IsNullOrWhiteSpace(title))
+                {
+                    info.Name = title;
+                }
+            }
+
+            var titleSort = FFProbeHelpers.GetDictionaryValue(tags, "titlesort");
+            if (!string.IsNullOrWhiteSpace(titleSort))
+            {
+                info.ForcedSortName = titleSort;
+            }
 
             info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort");
             info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number");
             info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name");
             info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
 
-            // Several different forms of retaildate
-            info.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
+            // Several different forms of retail/premiere date
+            info.PremiereDate =
+                FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
                 FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
                 FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
                 FFProbeHelpers.GetDictionaryDateTime(tags, "date_released") ??
                 FFProbeHelpers.GetDictionaryDateTime(tags, "date");
 
+            // Set common metadata for music (audio) and music videos (video)
+            info.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
+
+            var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
+
+            if (!string.IsNullOrWhiteSpace(artists))
+            {
+                info.Artists = SplitArtists(artists, new[] { '/', ';' }, false)
+                    .DistinctNames()
+                    .ToArray();
+            }
+            else
+            {
+                var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
+                if (string.IsNullOrWhiteSpace(artist))
+                {
+                    info.Artists = Array.Empty<string>();
+                }
+                else
+                {
+                    info.Artists = SplitArtists(artist, _nameDelimiters, true)
+                        .DistinctNames()
+                        .ToArray();
+                }
+            }
+
+            // If we don't have a ProductionYear try and get it from PremiereDate
+            if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue)
+            {
+                info.ProductionYear = info.PremiereDate.Value.Year;
+            }
+
+            // Set mediaType-specific metadata
             if (isAudio)
             {
                 SetAudioRuntimeTicks(data, info);
@@ -1079,13 +1127,13 @@ namespace MediaBrowser.MediaEncoding.Probing
 
         private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags)
         {
-            var peoples = new List<BaseItemPerson>();
+            var people = new List<BaseItemPerson>();
             var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
             if (!string.IsNullOrWhiteSpace(composer))
             {
                 foreach (var person in Split(composer, false))
                 {
-                    peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer });
+                    people.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer });
                 }
             }
 
@@ -1094,7 +1142,7 @@ namespace MediaBrowser.MediaEncoding.Probing
             {
                 foreach (var person in Split(conductor, false))
                 {
-                    peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor });
+                    people.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor });
                 }
             }
 
@@ -1103,46 +1151,21 @@ namespace MediaBrowser.MediaEncoding.Probing
             {
                 foreach (var person in Split(lyricist, false))
                 {
-                    peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist });
+                    people.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist });
                 }
             }
 
             // Check for writer some music is tagged that way as alternative to composer/lyricist
             var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer");
-
             if (!string.IsNullOrWhiteSpace(writer))
             {
                 foreach (var person in Split(writer, false))
                 {
-                    peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer });
+                    people.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer });
                 }
             }
 
-            audio.People = peoples.ToArray();
-            audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
-
-            var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
-
-            if (!string.IsNullOrWhiteSpace(artists))
-            {
-                audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false)
-                    .DistinctNames()
-                    .ToArray();
-            }
-            else
-            {
-                var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
-                if (string.IsNullOrWhiteSpace(artist))
-                {
-                    audio.Artists = Array.Empty<string>();
-                }
-                else
-                {
-                    audio.Artists = SplitArtists(artist, _nameDelimiters, true)
-                    .DistinctNames()
-                        .ToArray();
-                }
-            }
+            audio.People = people.ToArray();
 
             var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
             if (string.IsNullOrWhiteSpace(albumArtist))
@@ -1177,12 +1200,6 @@ namespace MediaBrowser.MediaEncoding.Probing
             // Disc number
             audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
 
-            // If we don't have a ProductionYear try and get it from PremiereDate
-            if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue)
-            {
-                audio.ProductionYear = audio.PremiereDate.Value.ToLocalTime().Year;
-            }
-
             // There's several values in tags may or may not be present
             FetchStudios(audio, tags, "organization");
             FetchStudios(audio, tags, "ensemble");

+ 2 - 0
MediaBrowser.Model/MediaInfo/MediaInfo.cs

@@ -51,6 +51,8 @@ namespace MediaBrowser.Model.MediaInfo
 
         public string ShowName { get; set; }
 
+        public string ForcedSortName { get; set; }
+
         public int? IndexNumber { get; set; }
 
         public int? ParentIndexNumber { get; set; }

+ 5 - 0
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs

@@ -111,6 +111,11 @@ namespace MediaBrowser.Providers.MediaInfo
                 audio.Name = data.Name;
             }
 
+            if (!string.IsNullOrEmpty(data.ForcedSortName))
+            {
+                audio.ForcedSortName = data.ForcedSortName;
+            }
+
             if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast))
             {
                 var people = new List<PersonInfo>();

+ 11 - 0
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -391,6 +391,12 @@ namespace MediaBrowser.Providers.MediaInfo
                 }
             }
 
+            if (video is MusicVideo musicVideo)
+            {
+                musicVideo.Album = data.Album;
+                musicVideo.Artists = data.Artists;
+            }
+
             if (data.ProductionYear.HasValue)
             {
                 if (!video.ProductionYear.HasValue || isFullRefresh)
@@ -433,6 +439,11 @@ namespace MediaBrowser.Providers.MediaInfo
                         video.Name = data.Name;
                     }
                 }
+
+                if (!string.IsNullOrWhiteSpace(data.ForcedSortName))
+                {
+                    video.ForcedSortName = data.ForcedSortName;
+                }
             }
 
             // If we don't have a ProductionYear try and get it from PremiereDate

+ 21 - 2
tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs

@@ -1,3 +1,5 @@
+using System;
+using System.Globalization;
 using System.IO;
 using System.Text.Json;
 using MediaBrowser.Common.Json;
@@ -17,9 +19,9 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
         [Fact]
         public void GetMediaInfo_MetaData_Success()
         {
-            var bytes = File.ReadAllBytes("Test Data/Probing/some_matadata.json");
+            var bytes = File.ReadAllBytes("Test Data/Probing/video_metadata.json");
             var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
-            MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/some_matadata.mkv", MediaProtocol.File);
+            MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/video_metadata.mkv", MediaProtocol.File);
 
             Assert.Single(res.MediaStreams);
 
@@ -52,5 +54,22 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
             Assert.Empty(res.Chapters);
             Assert.Equal("Just color bars", res.Overview);
         }
+
+        [Fact]
+        public void GetMediaInfo_MusicVideo_Success()
+        {
+            var bytes = File.ReadAllBytes("Test Data/Probing/music_video_metadata.json");
+            var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
+            MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/music_video.mkv", MediaProtocol.File);
+
+            Assert.Equal("The Title", res.Name);
+            Assert.Equal("Title, The", res.ForcedSortName);
+            Assert.Single(res.Artists);
+            Assert.Equal("The Artist", res.Artists[0]);
+            Assert.Equal("Album", res.Album);
+            Assert.Equal(2021, res.ProductionYear);
+            Assert.True(res.PremiereDate.HasValue);
+            Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate);
+        }
     }
 }

+ 111 - 0
tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_video_metadata.json

@@ -0,0 +1,111 @@
+{
+    "streams": [
+        {
+            "index": 0,
+            "codec_name": "h264",
+            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
+            "profile": "High",
+            "codec_type": "video",
+            "codec_time_base": "1001/48000",
+            "codec_tag_string": "[0][0][0][0]",
+            "codec_tag": "0x0000",
+            "width": 1920,
+            "height": 1080,
+            "coded_width": 1920,
+            "coded_height": 1088,
+            "closed_captions": 0,
+            "has_b_frames": 0,
+            "sample_aspect_ratio": "1:1",
+            "display_aspect_ratio": "16:9",
+            "pix_fmt": "yuv420p",
+            "level": 42,
+            "chroma_location": "left",
+            "field_order": "progressive",
+            "refs": 1,
+            "is_avc": "true",
+            "nal_length_size": "4",
+            "r_frame_rate": "24000/1001",
+            "avg_frame_rate": "24000/1001",
+            "time_base": "1/1000",
+            "start_pts": 0,
+            "start_time": "0.000000",
+            "bits_per_raw_sample": "8",
+            "disposition": {
+                "default": 1,
+                "dub": 0,
+                "original": 0,
+                "comment": 0,
+                "lyrics": 0,
+                "karaoke": 0,
+                "forced": 0,
+                "hearing_impaired": 0,
+                "visual_impaired": 0,
+                "clean_effects": 0,
+                "attached_pic": 0,
+                "timed_thumbnails": 0
+            },
+            "tags": {
+                "language": "eng"
+            }
+        },
+        {
+            "index": 1,
+            "codec_name": "aac",
+            "codec_long_name": "AAC (Advanced Audio Coding)",
+            "profile": "LC",
+            "codec_type": "audio",
+            "codec_time_base": "1/48000",
+            "codec_tag_string": "[0][0][0][0]",
+            "codec_tag": "0x0000",
+            "sample_fmt": "fltp",
+            "sample_rate": "48000",
+            "channels": 2,
+            "channel_layout": "stereo",
+            "bits_per_sample": 0,
+            "r_frame_rate": "0/0",
+            "avg_frame_rate": "0/0",
+            "time_base": "1/1000",
+            "start_pts": 0,
+            "start_time": "0.000000",
+            "disposition": {
+                "default": 1,
+                "dub": 0,
+                "original": 0,
+                "comment": 0,
+                "lyrics": 0,
+                "karaoke": 0,
+                "forced": 0,
+                "hearing_impaired": 0,
+                "visual_impaired": 0,
+                "clean_effects": 0,
+                "attached_pic": 0,
+                "timed_thumbnails": 0
+            },
+            "tags": {
+                "language": "eng"
+            }
+        }
+    ],
+    "chapters": [
+    ],
+    "format": {
+        "filename": "music_video.mkv",
+        "nb_streams": 2,
+        "nb_programs": 0,
+        "format_name": "matroska,webm",
+        "format_long_name": "Matroska / WebM",
+        "start_time": "0.000000",
+        "duration": "180.000000",
+        "size": "500000000",
+        "bit_rate": "22222222",
+        "probe_score": 100,
+        "tags": {
+            "TITLE-eng": "The Title",
+            "TITLESORT": "Title, The",
+            "ARTIST": "The Artist",
+            "ARTISTSORT": "Artist, The",
+            "ALBUM": "Album",
+            "DATE_RELEASED": "2021-01-01"
+        }
+    }
+}

+ 0 - 0
tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/some_matadata.json → tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json