aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs')
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs350
1 files changed, 46 insertions, 304 deletions
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index ea191dd08..d78f1b48e 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -1,15 +1,13 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -49,18 +47,14 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
- FFProbeHelpers.NormalizeFFProbeResult(result);
-
- cancellationToken.ThrowIfCancellationRequested();
-
await Fetch(item, cancellationToken, result).ConfigureAwait(false);
return ItemUpdateType.MetadataImport;
}
- private const string SchemaVersion = "1";
+ private const string SchemaVersion = "2";
- private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -71,7 +65,7 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
- return _json.DeserializeFromFile<InternalMediaInfoResult>(cachePath);
+ return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
}
catch (FileNotFoundException)
{
@@ -81,9 +75,13 @@ namespace MediaBrowser.Providers.MediaInfo
{
}
- var inputPath = new[] { item.Path };
+ var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = item.Path,
+ MediaType = DlnaProfileType.Audio,
+ Protocol = MediaProtocol.File
- var result = await _mediaEncoder.GetMediaInfo(inputPath, MediaProtocol.File, false, cancellationToken).ConfigureAwait(false);
+ }, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
_json.SerializeToFile(result, cachePath);
@@ -96,61 +94,23 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="audio">The audio.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="data">The data.</param>
+ /// <param name="mediaInfo">The media information.</param>
/// <returns>Task.</returns>
- protected Task Fetch(Audio audio, CancellationToken cancellationToken, InternalMediaInfoResult data)
+ protected Task Fetch(Audio audio, CancellationToken cancellationToken, Model.MediaInfo.MediaInfo mediaInfo)
{
- var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
- audio.FormatName = mediaInfo.Format;
- audio.TotalBitrate = mediaInfo.TotalBitrate;
+ audio.FormatName = mediaInfo.Container;
+ audio.TotalBitrate = mediaInfo.Bitrate;
audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage);
- if (data.streams != null)
- {
- // Get the first audio stream
- var stream = data.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
-
- if (stream != null)
- {
- // Get duration from stream properties
- var duration = stream.duration;
-
- // If it's not there go into format properties
- if (string.IsNullOrEmpty(duration))
- {
- duration = data.format.duration;
- }
-
- // If we got something, parse it
- if (!string.IsNullOrEmpty(duration))
- {
- audio.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks;
- }
- }
- }
-
- if (data.format != null)
- {
- var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
-
- audio.Container = extension;
+ audio.RunTimeTicks = mediaInfo.RunTimeTicks;
+ audio.Size = mediaInfo.Size;
- if (!string.IsNullOrEmpty(data.format.size))
- {
- audio.Size = long.Parse(data.format.size, _usCulture);
- }
- else
- {
- audio.Size = null;
- }
+ var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
+ audio.Container = extension;
- if (data.format.tags != null)
- {
- FetchDataFromTags(audio, data.format.tags);
- }
- }
+ FetchDataFromTags(audio, mediaInfo);
return _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken);
}
@@ -159,92 +119,37 @@ namespace MediaBrowser.Providers.MediaInfo
/// Fetches data from the tags dictionary
/// </summary>
/// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchDataFromTags(Audio audio, Dictionary<string, string> tags)
+ /// <param name="data">The data.</param>
+ private void FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo data)
{
- var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
-
// Only set Name if title was found in the dictionary
- if (!string.IsNullOrEmpty(title))
+ if (!string.IsNullOrEmpty(data.Title))
{
- audio.Name = title;
+ audio.Name = data.Title;
}
if (!audio.LockedFields.Contains(MetadataFields.Cast))
{
audio.People.Clear();
- var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
-
- if (!string.IsNullOrWhiteSpace(composer))
+ foreach (var person in data.People)
{
- foreach (var person in Split(composer, false))
+ audio.AddPerson(new PersonInfo
{
- audio.AddPerson(new PersonInfo { Name = person, Type = PersonType.Composer });
- }
+ Name = person.Name,
+ Type = person.Type,
+ Role = person.Role
+ });
}
}
- audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
-
- var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
-
- if (!string.IsNullOrWhiteSpace(artists))
- {
- audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- else
- {
- var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
- if (string.IsNullOrWhiteSpace(artist))
- {
- audio.Artists.Clear();
- }
- else
- {
- audio.Artists = SplitArtists(artist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- }
-
- var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist");
- }
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist");
- }
-
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- audio.AlbumArtists = new List<string>();
- }
- else
- {
- audio.AlbumArtists = SplitArtists(albumArtist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- }
-
- // Track number
- audio.IndexNumber = GetDictionaryDiscValue(tags, "track");
-
- // 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");
+ audio.Album = data.Album;
+ audio.Artists = data.Artists;
+ audio.AlbumArtists = data.AlbumArtists;
+ audio.IndexNumber = data.IndexNumber;
+ audio.ParentIndexNumber = data.ParentIndexNumber;
+ audio.ProductionYear = data.ProductionYear;
+ audio.PremiereDate = data.PremiereDate;
// If we don't have a ProductionYear try and get it from PremiereDate
if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue)
@@ -254,192 +159,29 @@ namespace MediaBrowser.Providers.MediaInfo
if (!audio.LockedFields.Contains(MetadataFields.Genres))
{
- FetchGenres(audio, tags);
- }
-
- if (!audio.LockedFields.Contains(MetadataFields.Studios))
- {
- audio.Studios.Clear();
-
- // There's several values in tags may or may not be present
- FetchStudios(audio, tags, "organization");
- FetchStudios(audio, tags, "ensemble");
- FetchStudios(audio, tags, "publisher");
- }
-
- // These support mulitple values, but for now we only store the first.
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")));
-
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzTrack, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")));
- }
-
- private string GetMultipleMusicBrainzId(string value)
- {
- if (string.IsNullOrWhiteSpace(value))
- {
- return null;
- }
-
- return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(i => i.Trim())
- .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
- }
-
- private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' };
-
- /// <summary>
- /// Splits the specified val.
- /// </summary>
- /// <param name="val">The val.</param>
- /// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
- /// <returns>System.String[][].</returns>
- private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
- {
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
- _nameDelimiters :
- new[] { ',' };
-
- return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
- }
-
- private const string ArtistReplaceValue = " | ";
-
- private IEnumerable<string> SplitArtists(string val)
- {
- val = val.Replace(" featuring ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase)
- .Replace(" feat. ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase);
-
- var artistsFound = new List<string>();
-
- foreach (var whitelistArtist in GetSplitWhitelist())
- {
- var originalVal = val;
- val = val.Replace(whitelistArtist, "|", StringComparison.OrdinalIgnoreCase);
-
- if (!string.Equals(originalVal, val, StringComparison.OrdinalIgnoreCase))
- {
- artistsFound.Add(whitelistArtist);
- }
- }
-
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = _nameDelimiters;
-
- var artists = val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
-
- artistsFound.AddRange(artists);
- return artistsFound;
- }
-
-
- private List<string> _splitWhiteList = null;
-
- private IEnumerable<string> GetSplitWhitelist()
- {
- if (_splitWhiteList == null)
- {
- var file = GetType().Namespace + ".whitelist.txt";
-
- using (var stream = GetType().Assembly.GetManifestResourceStream(file))
- {
- using (var reader = new StreamReader(stream))
- {
- var list = new List<string>();
-
- while (!reader.EndOfStream)
- {
- var val = reader.ReadLine();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- list.Add(val);
- }
- }
-
- _splitWhiteList = list;
- }
- }
- }
-
- return _splitWhiteList;
- }
-
- /// <summary>
- /// Gets the studios from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- private void FetchStudios(Audio audio, Dictionary<string, string> tags, string tagName)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, tagName);
-
- if (!string.IsNullOrEmpty(val))
- {
- // Sometimes the artist name is listed here, account for that
- var studios = Split(val, true).Where(i => !audio.HasAnyArtist(i));
-
- foreach (var studio in studios)
- {
- audio.AddStudio(studio);
- }
- }
- }
-
- /// <summary>
- /// Gets the genres from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchGenres(Audio audio, Dictionary<string, string> tags)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, "genre");
-
- if (!string.IsNullOrEmpty(val))
- {
audio.Genres.Clear();
- foreach (var genre in Split(val, true))
+ foreach (var genre in data.Genres)
{
audio.AddGenre(genre);
}
}
- }
-
- /// <summary>
- /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName)
- {
- var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName);
- if (!string.IsNullOrEmpty(disc))
+ if (!audio.LockedFields.Contains(MetadataFields.Studios))
{
- disc = disc.Split('/')[0];
-
- int num;
+ audio.Studios.Clear();
- if (int.TryParse(disc, out num))
+ foreach (var studio in data.Studios)
{
- return num;
+ audio.AddStudio(studio);
}
}
- return null;
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzArtist, data.GetProviderId(MetadataProviders.MusicBrainzArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, data.GetProviderId(MetadataProviders.MusicBrainzAlbum));
+ audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup));
+ audio.SetProviderId(MetadataProviders.MusicBrainzTrack, data.GetProviderId(MetadataProviders.MusicBrainzTrack));
}
-
}
}