mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	Merge pull request #5696 from Maxr1998/fix-music-video-metadata-probing
This commit is contained in:
		
						commit
						b12f509de3
					
				@ -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");
 | 
			
		||||
 | 
			
		||||
@ -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; }
 | 
			
		||||
 | 
			
		||||
@ -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>();
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user