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;
|
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.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort");
|
||||||
info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number");
|
info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number");
|
||||||
info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name");
|
info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name");
|
||||||
info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
|
info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
|
||||||
|
|
||||||
// Several different forms of retaildate
|
// Several different forms of retail/premiere date
|
||||||
info.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
|
info.PremiereDate =
|
||||||
|
FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
|
||||||
FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
|
FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
|
||||||
FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
|
FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
|
||||||
FFProbeHelpers.GetDictionaryDateTime(tags, "date_released") ??
|
FFProbeHelpers.GetDictionaryDateTime(tags, "date_released") ??
|
||||||
FFProbeHelpers.GetDictionaryDateTime(tags, "date");
|
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)
|
if (isAudio)
|
||||||
{
|
{
|
||||||
SetAudioRuntimeTicks(data, info);
|
SetAudioRuntimeTicks(data, info);
|
||||||
|
@ -1079,13 +1127,13 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
|
|
||||||
private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags)
|
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");
|
var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
|
||||||
if (!string.IsNullOrWhiteSpace(composer))
|
if (!string.IsNullOrWhiteSpace(composer))
|
||||||
{
|
{
|
||||||
foreach (var person in Split(composer, false))
|
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))
|
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))
|
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
|
// Check for writer some music is tagged that way as alternative to composer/lyricist
|
||||||
var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer");
|
var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer");
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(writer))
|
if (!string.IsNullOrWhiteSpace(writer))
|
||||||
{
|
{
|
||||||
foreach (var person in Split(writer, false))
|
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.People = people.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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
|
var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
|
||||||
if (string.IsNullOrWhiteSpace(albumArtist))
|
if (string.IsNullOrWhiteSpace(albumArtist))
|
||||||
|
@ -1177,12 +1200,6 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
// Disc number
|
// Disc number
|
||||||
audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
|
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
|
// There's several values in tags may or may not be present
|
||||||
FetchStudios(audio, tags, "organization");
|
FetchStudios(audio, tags, "organization");
|
||||||
FetchStudios(audio, tags, "ensemble");
|
FetchStudios(audio, tags, "ensemble");
|
||||||
|
|
|
@ -51,6 +51,8 @@ namespace MediaBrowser.Model.MediaInfo
|
||||||
|
|
||||||
public string ShowName { get; set; }
|
public string ShowName { get; set; }
|
||||||
|
|
||||||
|
public string ForcedSortName { get; set; }
|
||||||
|
|
||||||
public int? IndexNumber { get; set; }
|
public int? IndexNumber { get; set; }
|
||||||
|
|
||||||
public int? ParentIndexNumber { get; set; }
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
|
|
@ -111,6 +111,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
audio.Name = data.Name;
|
audio.Name = data.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(data.ForcedSortName))
|
||||||
|
{
|
||||||
|
audio.ForcedSortName = data.ForcedSortName;
|
||||||
|
}
|
||||||
|
|
||||||
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>();
|
||||||
|
|
|
@ -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 (data.ProductionYear.HasValue)
|
||||||
{
|
{
|
||||||
if (!video.ProductionYear.HasValue || isFullRefresh)
|
if (!video.ProductionYear.HasValue || isFullRefresh)
|
||||||
|
@ -433,6 +439,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
video.Name = data.Name;
|
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
|
// 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.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using MediaBrowser.Common.Json;
|
using MediaBrowser.Common.Json;
|
||||||
|
@ -17,9 +19,9 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetMediaInfo_MetaData_Success()
|
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);
|
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);
|
Assert.Single(res.MediaStreams);
|
||||||
|
|
||||||
|
@ -52,5 +54,22 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
|
||||||
Assert.Empty(res.Chapters);
|
Assert.Empty(res.Chapters);
|
||||||
Assert.Equal("Just color bars", res.Overview);
|
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…
Reference in New Issue
Block a user