Пример #1
0
        public void TestNfoMovieReaderReadMetadata()
        {
            //Arrange
            var resourceProviders = new Dictionary <Guid, IResourceProvider>();

            resourceProviders.Add(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, new LocalFsResourceProvider());
            var mockMediaAccessor = new Mock <IMediaAccessor>();

            ServiceRegistration.Set <IMediaAccessor>(mockMediaAccessor.Object);
            mockMediaAccessor.Setup(x => x.LocalResourceProviders).Returns(resourceProviders);

            Mock <IFileSystemResourceAccessor> mockRA = new Mock <IFileSystemResourceAccessor>();

            mockRA.Setup(r => r.OpenReadAsync()).Returns(Task.FromResult(
                                                             Assembly.GetExecutingAssembly().GetManifestResourceStream("Tests.Server.NfoMetadataExtractor.TestData.MovieNfo.movie.nfo")));
            mockRA.SetupGet(t => t.CanonicalLocalResourcePath).Returns(ResourcePath.BuildBaseProviderPath(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, @"TestData\MovieNfo\movie.nfo"));
            NfoMovieReader reader = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, false, false, false, null, new NfoMovieMetadataExtractorSettings());

            //Act
            reader.TryReadMetadataAsync(mockRA.Object).Wait();
            var stubs = reader.GetMovieStubs();

            //Assert
            Assert.NotNull(stubs);
            Assert.AreEqual(1, stubs.Count);
            var stub = stubs[0];

            Assert.NotNull(stub);
            Assert.AreEqual("The Lego Batman Movie", stub.Title);
            Assert.AreEqual("The Lego Batman Movie", stub.OriginalTitle);
            Assert.AreEqual(7.2m, stub.Rating);
            Assert.AreEqual(new DateTime(2017, 1, 1), stub.Year);
            Assert.AreEqual(1853, stub.Votes);
            Assert.AreEqual("In the irreverent spirit of fun that made “The Lego Movie” a worldwide phenomenon, the self-described leading man of that ensemble—Lego Batman—stars in his own big-screen adventure. But there are big changes...", stub.Outline);
            Assert.AreEqual("In the irreverent spirit of fun that made “The Lego Movie” a worldwide phenomenon, the self-described leading man of that ensemble—Lego Batman—stars in his own big-screen adventure. But there are big changes brewing in Gotham, and if he wants to save the city from The Joker’s hostile takeover, Batman may have to drop the lone vigilante thing, try to work with others and maybe, just maybe, learn to lighten up.", stub.Plot);
            Assert.AreEqual("Always be yourself. Unless you can be Batman.", stub.Tagline);
            Assert.AreEqual(TimeSpan.FromMinutes(104), stub.Runtime);
            CollectionAssert.AreEqual(new[] { "UK:U" }, stub.Mpaa);
            CollectionAssert.AreEqual(new[] { "UK:U" }, stub.Certification);
            Assert.AreEqual("tt4116284", stub.Id);
            Assert.AreEqual(324849, stub.TmdbId);
            CollectionAssert.AreEqual(new[] { "Denmark", "United States" }, stub.Countries);
            Assert.AreEqual(false, stub.Watched);
            Assert.AreEqual(0, stub.PlayCount);
            CollectionAssert.AreEqual(new[] { "Action", "Animation", "Comedy", "Family", "Fantasy" }, stub.Genres);
            CollectionAssert.AreEqual(new[] { "Lin Pictures", "Warner Bros. Animation", "Warner Bros.", "Animal Logic", "DC Entertainment", "Lord Miller", "LEGO System A", "S" }, stub.Studios);
            CollectionAssert.AreEqual(new[] { "Chris McKenna", "Erik Sommers", "Seth Grahame-Smith", "Jared Stern", "John Whittington" }, stub.Credits);
            Assert.AreEqual("Chris McKay", stub.Director);
            CollectionAssert.AreEqual(new[] { "English" }, stub.Languages);
        }
Пример #2
0
        public void TestNfoMovieReaderWriteActorMetadata()
        {
            //Arrange
            IList <PersonStub> actors    = CreateTestActors();
            MovieStub          movieStub = CreateTestMovieStub(actors);
            NfoMovieReader     reader    = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, true, false, false, null, new NfoMovieMetadataExtractorSettings());

            reader.GetMovieStubs().Add(movieStub);

            //Act
            IList <IDictionary <Guid, IList <MediaItemAspect> > > aspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >();

            reader.TryWriteActorMetadata(aspects);

            //Assert
            Assert.AreEqual(2, aspects.Count);
            MediaItemAspect personAspect0 = MediaItemAspect.GetAspect(aspects[0], PersonAspect.Metadata);

            Assert.NotNull(personAspect0);
            Assert.AreEqual(actors[0].Name, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_PERSON_NAME));
            Assert.AreEqual(actors[0].Biography, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_BIOGRAPHY));
            Assert.AreEqual(actors[0].Birthdate, personAspect0.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFBIRTH));
            Assert.AreEqual(actors[0].Deathdate, personAspect0.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFDEATH));
            Assert.AreEqual(PersonAspect.OCCUPATION_ACTOR, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_OCCUPATION));
            IList <MediaItemAspect> externalIdentifiers0;

            Assert.IsTrue(aspects[0].TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers0));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers0, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_PERSON, actors[0].ImdbId));

            MediaItemAspect personAspect1 = MediaItemAspect.GetAspect(aspects[1], PersonAspect.Metadata);

            Assert.NotNull(personAspect1);
            Assert.AreEqual(actors[1].Name, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_PERSON_NAME));
            Assert.AreEqual(actors[1].Biography, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_BIOGRAPHY));
            Assert.AreEqual(actors[1].Birthdate, personAspect1.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFBIRTH));
            Assert.AreEqual(actors[1].Deathdate, personAspect1.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFDEATH));
            Assert.AreEqual(PersonAspect.OCCUPATION_ACTOR, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_OCCUPATION));
            IList <MediaItemAspect> externalIdentifiers1;

            Assert.IsTrue(aspects[1].TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers1));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers1, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_PERSON, actors[1].ImdbId));
        }
Пример #3
0
        public override async Task CollectFanArtAsync(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            IResourceLocator mediaItemLocator = null;

            if (!BaseInfo.IsVirtualResource(aspects))
            {
                mediaItemLocator = GetResourceLocator(aspects);
            }

            if (!aspects.ContainsKey(MovieAspect.ASPECT_ID) || mediaItemLocator == null)
            {
                return;
            }

            IFanArtCache fanArtCache = ServiceRegistration.Get <IFanArtCache>();

            using (IResourceAccessor mediaItemAccessor = mediaItemLocator.CreateAccessor())
            {
                IList <Tuple <Guid, string> > actors = GetActors(aspects);

                //Check if loading nfo is needed
                if ((actors?.All(a => IsInCache(a.Item1)) ?? true) && IsInCache(mediaItemId))
                {
                    return; //Everything was already saved
                }
                NfoMovieReader movieNfoReader = await MOVIE_EXTRACTOR.TryGetNfoMovieReaderAsync(mediaItemAccessor, true).ConfigureAwait(false);

                if (movieNfoReader != null)
                {
                    //Movie fanart
                    var stubs    = movieNfoReader.GetMovieStubs();
                    var mainStub = stubs?.FirstOrDefault();
                    if (AddToCache(mediaItemId))
                    {
                        if (mainStub?.Thumb != null)
                        {
                            await fanArtCache.TrySaveFanArt(mediaItemId, mainStub.Title, FanArtTypes.Poster, p => TrySaveFileImage(mainStub.Thumb, p, "Thumb", "Nfo.")).ConfigureAwait(false);
                        }

                        await TrySaveFanArt(fanArtCache, FanArtTypes.FanArt, "FanArt", mainStub?.FanArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.DiscArt, "DiscArt", mainStub?.DiscArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Logo, "Logo", mainStub?.Logos, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.ClearArt, "ClearArt", mainStub?.ClearArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Banner, "Banner", mainStub?.Banners, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Thumbnail, "Landscape", mainStub?.Landscape, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                    }

                    //Actor fanart
                    if (actors != null)
                    {
                        foreach (var actor in actors)
                        {
                            if (!IsInCache(actor.Item1))
                            {
                                var existingThumbs = fanArtCache.GetFanArtFiles(actor.Item1, FanArtTypes.Thumbnail);
                                var actorStub      = mainStub?.Actors?.FirstOrDefault(a => string.Equals(a?.Name, actor.Item2, StringComparison.InvariantCultureIgnoreCase));
                                if (actorStub != null || existingThumbs.Any()) //We have a thumb already or no thumb is available, so no need to check again
                                {
                                    AddToCache(actor.Item1);
                                }

                                if (actorStub?.Thumb != null)
                                {
                                    await fanArtCache.TrySaveFanArt(actor.Item1, actor.Item2, FanArtTypes.Thumbnail, p => TrySaveFileImage(actorStub.Thumb, p, "Thumb", "Nfo.")).ConfigureAwait(false);
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #4
0
        public void TestNfoMovieReaderWriteMetadata()
        {
            //Arrange
            MovieStub      movieStub       = CreateTestMovieStub(CreateTestActors());
            NfoMovieReader readerVideoOnly = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, true, false, false, null, new NfoMovieMetadataExtractorSettings());

            readerVideoOnly.GetMovieStubs().Add(movieStub);
            NfoMovieReader readerMovieOnly = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, false, false, false, null, new NfoMovieMetadataExtractorSettings());

            readerMovieOnly.GetMovieStubs().Add(movieStub);

            //Act
            IDictionary <Guid, IList <MediaItemAspect> > aspectsVideoOnly = new Dictionary <Guid, IList <MediaItemAspect> >();

            readerVideoOnly.TryWriteMetadata(aspectsVideoOnly);
            IDictionary <Guid, IList <MediaItemAspect> > aspectsMovieOnly = new Dictionary <Guid, IList <MediaItemAspect> >();

            readerMovieOnly.TryWriteMetadata(aspectsMovieOnly);

            //Assert

            //Video aspects only
            MediaItemAspect mediaAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, MediaAspect.Metadata);

            Assert.NotNull(mediaAspect);
            Assert.AreEqual(movieStub.Title, mediaAspect.GetAttributeValue <string>(MediaAspect.ATTR_TITLE));
            Assert.AreEqual(movieStub.SortTitle, mediaAspect.GetAttributeValue <string>(MediaAspect.ATTR_SORT_TITLE));
            Assert.AreEqual(movieStub.Premiered, mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_RECORDINGTIME));
            Assert.AreEqual(movieStub.PlayCount, mediaAspect.GetAttributeValue <int?>(MediaAspect.ATTR_PLAYCOUNT));
            Assert.AreEqual(movieStub.LastPlayed, mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_LASTPLAYED));

            MediaItemAspect videoAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, VideoAspect.Metadata);

            Assert.NotNull(videoAspect);
            Assert.AreEqual(movieStub.Plot, videoAspect.GetAttributeValue <string>(VideoAspect.ATTR_STORYPLOT));
            CollectionAssert.AreEqual(movieStub.Actors.OrderBy(p => p.Order).Select(p => p.Name), videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS));
            Assert.AreEqual(movieStub.Director, videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_DIRECTORS).First());
            CollectionAssert.AreEqual(movieStub.Credits, videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_WRITERS));

            //ToDo: Rework Genre Mapper to make it testable, currently depends on IPathManager/language files!
            //IList<MediaItemAspect> genreAspects;
            //Assert.IsTrue(aspects.TryGetValue(GenreAspect.ASPECT_ID, out genreAspects));
            //CollectionAssert.AreEqual(movieStub.Genres, genreAspects.Select(g => g.GetAttributeValue<string>(GenreAspect.ATTR_GENRE)));

            MediaItemAspect thumbnailAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, ThumbnailLargeAspect.Metadata);

            Assert.NotNull(thumbnailAspect);
            CollectionAssert.AreEqual(movieStub.Thumb, thumbnailAspect.GetAttributeValue <byte[]>(ThumbnailLargeAspect.ATTR_THUMBNAIL));

            //Movie aspects only
            MediaItemAspect movieAspect = MediaItemAspect.GetAspect(aspectsMovieOnly, MovieAspect.Metadata);

            Assert.NotNull(movieAspect);
            CollectionAssert.AreEqual(movieStub.Companies, movieAspect.GetCollectionAttribute <string>(MovieAspect.ATTR_COMPANIES));
            Assert.AreEqual(movieStub.Title, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_MOVIE_NAME));
            Assert.AreEqual(movieStub.OriginalTitle, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_ORIG_MOVIE_NAME));
            Assert.AreEqual(movieStub.Sets.OrderBy(set => set.Order).First().Name, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_COLLECTION_NAME));
            Assert.AreEqual((int)movieStub.Runtime.Value.TotalMinutes, movieAspect.GetAttributeValue <int?>(MovieAspect.ATTR_RUNTIME_M));
            Assert.AreEqual("US_PG", movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_CERTIFICATION));
            Assert.AreEqual(movieStub.Tagline, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_TAGLINE));
            Assert.AreEqual((double)movieStub.Rating, movieAspect.GetAttributeValue <double?>(MovieAspect.ATTR_TOTAL_RATING));
            Assert.AreEqual(movieStub.Votes, movieAspect.GetAttributeValue <int?>(MovieAspect.ATTR_RATING_COUNT));

            IList <MediaItemAspect> externalIdentifiers;

            Assert.IsTrue(aspectsMovieOnly.TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.TmdbId.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_COLLECTION, movieStub.TmdbCollectionId.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Id));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_ALLOCINE, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Allocine.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_CINEPASSION, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Cinepassion.ToString()));
        }
        /// <summary>
        /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param>
        /// </summary>
        /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param>
        /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param>
        /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param>
        /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns>
        private async Task <bool> TryExtractMovieMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode)
        {
            // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier.
            // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries
            // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry.
            var  miNumber = Interlocked.Increment(ref _lastMediaItemNumber);
            bool isStub   = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID);

            try
            {
                _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode);

                // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor.
                // Otherwise it is not possible to find a nfo-file in the MediaItem's directory.
                if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber);
                    return(false);
                }

                // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before
                // has identified this MediaItem as a video and therefore added a VideoAspect.
                if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber);
                    return(false);
                }

                // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file.
                // If we don't find one, we cannot extract any metadata.
                IFileSystemResourceAccessor nfoFsra;
                if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra))
                {
                    return(false);
                }

                // Now we (asynchronously) extract the metadata into a stub object.
                // If there is an error parsing the nfo-file with XmlNfoReader, we at least try to parse for a valid IMDB-ID.
                // If no metadata was found, nothing can be stored in the MediaItemAspects.
                NfoMovieReader nfoReader = new NfoMovieReader(_debugLogger, miNumber, false, forceQuickMode, isStub, _httpClient, _settings);
                using (nfoFsra)
                {
                    if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false) &&
                        !await nfoReader.TryParseForImdbId(nfoFsra).ConfigureAwait(false))
                    {
                        _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber);
                        return(false);
                    }
                    else if (isStub)
                    {
                        Stubs.MovieStub movie = nfoReader.GetMovieStubs().FirstOrDefault();
                        if (movie != null)
                        {
                            IList <MultipleMediaItemAspect> providerResourceAspects;
                            if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects))
                            {
                                MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB);
                                string mime = null;
                                if (movie.FileInfo != null && movie.FileInfo.Count > 0)
                                {
                                    mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + movie.FileInfo.First().Container);
                                }
                                if (mime != null)
                                {
                                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime);
                                }
                            }

                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, movie.Title);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, movie.SortTitle != null ? movie.SortTitle : BaseInfo.GetSortTitle(movie.Title));
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, movie.Premiered.HasValue ? movie.Premiered.Value : movie.Year.HasValue ? movie.Year.Value : (DateTime?)null);

                            if (movie.FileInfo != null && movie.FileInfo.Count > 0)
                            {
                                extractedAspectData.Remove(VideoStreamAspect.ASPECT_ID);
                                extractedAspectData.Remove(VideoAudioStreamAspect.ASPECT_ID);
                                extractedAspectData.Remove(SubtitleAspect.ASPECT_ID);
                                StubParser.ParseFileInfo(extractedAspectData, movie.FileInfo, movie.Title, movie.Fps);
                            }
                        }
                    }
                }

                //Check reimport
                if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID))
                {
                    MovieInfo reimport = new MovieInfo();
                    reimport.FromMetadata(extractedAspectData);
                    if (!VerifyMovieReimport(nfoReader, reimport))
                    {
                        ServiceRegistration.Get <ILogger>().Info("NfoMovieMetadataExtractor: Nfo movie metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport);
                        return(false);
                    }
                }

                // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is
                // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false.
                if (!nfoReader.TryWriteMetadata(extractedAspectData))
                {
                    _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber);
                    return(false);
                }

                _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber);
                ServiceRegistration.Get <ILogger>().Debug("NfoMovieMetadataExtractor: Assigned nfo movie metadata for resource '{0}'", mediaItemAccessor);
                return(true);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor);
                _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber);
                return(false);
            }
        }