diff options
Diffstat (limited to 'MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs')
| -rw-r--r-- | MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs | 350 |
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)); } - } } |
