diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 30e50fecd6..ced36f3aa5 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -129,7 +129,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// The request.
/// The cancellation token.
/// Task.
- public Task GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken)
+ public Task GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken)
{
var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters;
@@ -175,7 +175,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// The cancellation token.
/// Task{MediaInfoResult}.
/// ffprobe failed - streams and format are both null.
- private async Task GetMediaInfoInternal(string inputPath,
+ private async Task GetMediaInfoInternal(string inputPath,
string primaryPath,
MediaProtocol protocol,
bool extractChapters,
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 31f6af1810..db6278bd46 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -27,7 +27,7 @@ namespace MediaBrowser.MediaEncoding.Probing
public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType videoType, bool isAudio, string path, MediaProtocol protocol)
{
- var info = new Model.MediaInfo.MediaInfo
+ var info = new MediaInfo
{
Path = path,
Protocol = protocol
@@ -56,40 +56,81 @@ namespace MediaBrowser.MediaEncoding.Probing
}
}
- if (isAudio)
- {
- SetAudioRuntimeTicks(data, info);
+ var tags = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ var tagStreamType = isAudio ? "audio" : "video";
- var tags = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
- // tags are normally located under data.format, but we've seen some cases with ogg where they're part of the audio stream
- // so let's create a combined list of both
+ if (data.streams != null)
+ {
+ var tagStream = data.streams.FirstOrDefault(i => string.Equals(i.codec_type, tagStreamType, StringComparison.OrdinalIgnoreCase));
- if (data.streams != null)
+ if (tagStream != null && tagStream.tags != null)
{
- var audioStream = data.streams.FirstOrDefault(i => string.Equals(i.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
-
- if (audioStream != null && audioStream.tags != null)
+ foreach (var pair in tagStream.tags)
{
- foreach (var pair in audioStream.tags)
- {
- tags[pair.Key] = pair.Value;
- }
+ tags[pair.Key] = pair.Value;
}
}
+ }
- if (data.format != null && data.format.tags != null)
+ if (data.format != null && data.format.tags != null)
+ {
+ foreach (var pair in data.format.tags)
{
- foreach (var pair in data.format.tags)
- {
- tags[pair.Key] = pair.Value;
- }
+ tags[pair.Key] = pair.Value;
}
+ }
+
+ FetchGenres(info, tags);
+ var overview = FFProbeHelpers.GetDictionaryValue(tags, "description");
+ if (!string.IsNullOrWhiteSpace(overview))
+ {
+ info.Overview = overview;
+ }
+
+ var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
+ if (!string.IsNullOrWhiteSpace(title))
+ {
+ info.Name = title;
+ }
+
+ info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
+
+ // Several different forms of retaildate
+ info.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "date");
+
+ if (isAudio)
+ {
+ SetAudioRuntimeTicks(data, info);
+
+ // tags are normally located under data.format, but we've seen some cases with ogg where they're part of the audio stream
+ // so let's create a combined list of both
SetAudioInfoFromTags(info, tags);
}
else
{
+ var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC");
+ if (!string.IsNullOrWhiteSpace(iTunEXTC))
+ {
+ var parts = iTunEXTC.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+ // Example
+ // mpaa|G|100|For crude humor
+ if (parts.Length == 4)
+ {
+ info.OfficialRating = parts[1];
+ info.OfficialRatingDescription = parts[3];
+ }
+ }
+
+ var itunesXml = FFProbeHelpers.GetDictionaryValue(tags, "iTunMOVI");
+ if (!string.IsNullOrWhiteSpace(itunesXml))
+ {
+ FetchFromItunesInfo(itunesXml, info);
+ }
+
if (data.format != null && !string.IsNullOrEmpty(data.format.duration))
{
info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
@@ -108,6 +149,11 @@ namespace MediaBrowser.MediaEncoding.Probing
return info;
}
+ private void FetchFromItunesInfo(string xml, MediaInfo info)
+ {
+
+ }
+
///
/// Converts ffprobe stream info to our MediaStream class
///
@@ -430,16 +476,8 @@ namespace MediaBrowser.MediaEncoding.Probing
}
}
- private void SetAudioInfoFromTags(Model.MediaInfo.MediaInfo audio, Dictionary tags)
+ private void SetAudioInfoFromTags(MediaInfo audio, Dictionary tags)
{
- var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
-
- // Only set Name if title was found in the dictionary
- if (!string.IsNullOrEmpty(title))
- {
- audio.Title = title;
- }
-
var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
if (!string.IsNullOrWhiteSpace(composer))
{
@@ -511,22 +549,12 @@ namespace MediaBrowser.MediaEncoding.Probing
// Disc number
audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
- audio.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
-
- // Several different forms of retaildate
- audio.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "date");
-
// 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;
}
- FetchGenres(audio, tags);
-
// There's several values in tags may or may not be present
FetchStudios(audio, tags, "organization");
FetchStudios(audio, tags, "ensemble");
@@ -693,7 +721,7 @@ namespace MediaBrowser.MediaEncoding.Probing
///
/// The information.
/// The tags.
- private void FetchGenres(Model.MediaInfo.MediaInfo info, Dictionary tags)
+ private void FetchGenres(MediaInfo info, Dictionary tags)
{
var val = FFProbeHelpers.GetDictionaryValue(tags, "genre");
@@ -764,7 +792,7 @@ namespace MediaBrowser.MediaEncoding.Probing
private const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames)
- private void FetchWtvInfo(Model.MediaInfo.MediaInfo video, InternalMediaInfoResult data)
+ private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data)
{
if (data.format == null || data.format.tags == null)
{
@@ -775,15 +803,16 @@ namespace MediaBrowser.MediaEncoding.Probing
if (!string.IsNullOrWhiteSpace(genres))
{
- //genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "genre");
- }
-
- if (!string.IsNullOrWhiteSpace(genres))
- {
- video.Genres = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
+ var genreList = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(i => !string.IsNullOrWhiteSpace(i))
.Select(i => i.Trim())
.ToList();
+
+ // If this is empty then don't overwrite genres that might have been fetched earlier
+ if (genreList.Count > 0)
+ {
+ video.Genres = genreList;
+ }
}
var officialRating = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/ParentalRating");
diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs
index 21f258693e..1267101976 100644
--- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs
+++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs
@@ -9,11 +9,6 @@ namespace MediaBrowser.Model.MediaInfo
{
public List Chapters { get; set; }
- ///
- /// Gets or sets the title.
- ///
- /// The title.
- public string Title { get; set; }
///
/// Gets or sets the album.
///
@@ -47,6 +42,11 @@ namespace MediaBrowser.Model.MediaInfo
/// The official rating.
public string OfficialRating { get; set; }
///
+ /// Gets or sets the official rating description.
+ ///
+ /// The official rating description.
+ public string OfficialRatingDescription { get; set; }
+ ///
/// Gets or sets the overview.
///
/// The overview.
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index 4cf507d153..78906fa852 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -125,9 +125,9 @@ namespace MediaBrowser.Providers.MediaInfo
private async Task FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo data)
{
// Only set Name if title was found in the dictionary
- if (!string.IsNullOrEmpty(data.Title))
+ if (!string.IsNullOrEmpty(data.Name))
{
- audio.Name = data.Title;
+ audio.Name = data.Name;
}
if (!audio.LockedFields.Contains(MetadataFields.Cast))
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index ebbc045abf..fb8e258921 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -383,6 +383,11 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
+ if (!string.IsNullOrWhiteSpace(data.OfficialRatingDescription) || isFullRefresh)
+ {
+ video.OfficialRatingDescription = data.OfficialRatingDescription;
+ }
+
if (!video.LockedFields.Contains(MetadataFields.Genres))
{
if (video.Genres.Count == 0 || isFullRefresh)
@@ -437,6 +442,13 @@ namespace MediaBrowser.Providers.MediaInfo
video.ParentIndexNumber = data.ParentIndexNumber;
}
}
+ if (!string.IsNullOrWhiteSpace(data.Name))
+ {
+ if (string.IsNullOrWhiteSpace(video.Name) || string.Equals(video.Name, Path.GetFileNameWithoutExtension(video.Path), StringComparison.OrdinalIgnoreCase))
+ {
+ video.Name = data.Name;
+ }
+ }
// If we don't have a ProductionYear try and get it from PremiereDate
if (video.PremiereDate.HasValue && !video.ProductionYear.HasValue)
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 9de20cb396..d4d8be7f1a 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -140,6 +140,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -254,9 +257,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest