private void AddMediaInfoTokens(Dictionary <string, Func <TokenMatch, string> > tokenHandlers, MovieFile movieFile) { if (movieFile.MediaInfo == null) { _logger.Trace("Media info is unavailable for {0}", movieFile); return; } var sceneName = movieFile.GetSceneOrFileName(); var videoCodec = MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, sceneName); var audioCodec = MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, sceneName); var audioChannels = MediaInfoFormatter.FormatAudioChannels(movieFile.MediaInfo); var audioLanguages = movieFile.MediaInfo.AudioLanguages ?? new List <string>(); var subtitles = movieFile.MediaInfo.Subtitles ?? new List <string>(); var mediaInfoAudioLanguages = GetLanguagesToken(audioLanguages); if (!mediaInfoAudioLanguages.IsNullOrWhiteSpace()) { mediaInfoAudioLanguages = $"[{mediaInfoAudioLanguages}]"; } var mediaInfoAudioLanguagesAll = mediaInfoAudioLanguages; if (mediaInfoAudioLanguages == "[EN]") { mediaInfoAudioLanguages = string.Empty; } var mediaInfoSubtitleLanguages = GetLanguagesToken(subtitles); if (!mediaInfoSubtitleLanguages.IsNullOrWhiteSpace()) { mediaInfoSubtitleLanguages = $"[{mediaInfoSubtitleLanguages}]"; } var videoBitDepth = movieFile.MediaInfo.VideoBitDepth > 0 ? movieFile.MediaInfo.VideoBitDepth.ToString() : 8.ToString(); var audioChannelsFormatted = audioChannels > 0 ? audioChannels.ToString("F1", CultureInfo.InvariantCulture) : string.Empty; var mediaInfo3D = movieFile.MediaInfo.VideoMultiViewCount > 1 ? "3D" : string.Empty; tokenHandlers["{MediaInfo Video}"] = m => videoCodec; tokenHandlers["{MediaInfo VideoCodec}"] = m => videoCodec; tokenHandlers["{MediaInfo VideoBitDepth}"] = m => videoBitDepth; tokenHandlers["{MediaInfo Audio}"] = m => audioCodec; tokenHandlers["{MediaInfo AudioCodec}"] = m => audioCodec; tokenHandlers["{MediaInfo AudioChannels}"] = m => audioChannelsFormatted; tokenHandlers["{MediaInfo AudioLanguages}"] = m => mediaInfoAudioLanguages; tokenHandlers["{MediaInfo AudioLanguagesAll}"] = m => mediaInfoAudioLanguagesAll; tokenHandlers["{MediaInfo SubtitleLanguages}"] = m => mediaInfoSubtitleLanguages; tokenHandlers["{MediaInfo SubtitleLanguagesAll}"] = m => mediaInfoSubtitleLanguages; tokenHandlers["{MediaInfo 3D}"] = m => mediaInfo3D; tokenHandlers["{MediaInfo Simple}"] = m => $"{videoCodec} {audioCodec}"; tokenHandlers["{MediaInfo Full}"] = m => $"{videoCodec} {audioCodec}{mediaInfoAudioLanguages} {mediaInfoSubtitleLanguages}"; tokenHandlers[MediaInfoVideoDynamicRangeToken] = m => MediaInfoFormatter.FormatVideoDynamicRange(movieFile.MediaInfo); tokenHandlers[MediaInfoVideoDynamicRangeTypeToken] = m => MediaInfoFormatter.FormatVideoDynamicRangeType(movieFile.MediaInfo); }
public override MetadataFileResult MovieMetadata(Movie movie, MovieFile movieFile) { if (!Settings.MovieMetadata) { return(null); } _logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath); var xmlResult = string.Empty; var sb = new StringBuilder(); var xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; xws.Indent = false; using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot); var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster); var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart); var details = new XElement("movie"); details.Add(new XElement("title", movie.Title)); if (movie.Ratings != null && movie.Ratings.Votes > 0) { details.Add(new XElement("rating", movie.Ratings.Value)); } details.Add(new XElement("plot", movie.Overview)); details.Add(new XElement("id", movie.ImdbId)); if (movie.ImdbId.IsNotNullOrWhiteSpace()) { var imdbId = new XElement("uniqueid", movie.ImdbId); imdbId.SetAttributeValue("type", "imdb"); imdbId.SetAttributeValue("default", true); details.Add(imdbId); } var uniqueId = new XElement("uniqueid", movie.TmdbId); uniqueId.SetAttributeValue("type", "tmdb"); details.Add(uniqueId); details.Add(new XElement("year", movie.Year)); if (movie.InCinemas.HasValue) { details.Add(new XElement("premiered", movie.InCinemas.Value.ToString("yyyy-MM-dd"))); } foreach (var genre in movie.Genres) { details.Add(new XElement("genre", genre)); } details.Add(new XElement("studio", movie.Studio)); if (thumbnail == null) { details.Add(new XElement("thumb")); } else { details.Add(new XElement("thumb", thumbnail.Url)); } foreach (var poster in posters) { if (poster != null && poster.Url != null) { details.Add(new XElement("thumb", new XAttribute("aspect", "poster"), poster.Url)); } } if (fanarts.Count() > 0) { var fanartElement = new XElement("fanart"); foreach (var fanart in fanarts) { if (fanart != null && fanart.Url != null) { fanartElement.Add(new XElement("thumb", fanart.Url)); } } details.Add(fanartElement); } details.Add(new XElement("watched", watched)); if (movieFile.MediaInfo != null) { var sceneName = movieFile.GetSceneOrFileName(); var fileInfo = new XElement("fileinfo"); var streamDetails = new XElement("streamdetails"); var video = new XElement("video"); video.Add(new XElement("aspect", (float)movieFile.MediaInfo.Width / (float)movieFile.MediaInfo.Height)); video.Add(new XElement("bitrate", movieFile.MediaInfo.VideoBitrate)); video.Add(new XElement("codec", MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, sceneName))); video.Add(new XElement("framerate", movieFile.MediaInfo.VideoFps)); video.Add(new XElement("height", movieFile.MediaInfo.Height)); video.Add(new XElement("scantype", movieFile.MediaInfo.ScanType)); video.Add(new XElement("width", movieFile.MediaInfo.Width)); if (movieFile.MediaInfo.RunTime != null) { video.Add(new XElement("duration", movieFile.MediaInfo.RunTime.TotalMinutes)); video.Add(new XElement("durationinseconds", movieFile.MediaInfo.RunTime.TotalSeconds)); } streamDetails.Add(video); var audio = new XElement("audio"); audio.Add(new XElement("bitrate", movieFile.MediaInfo.AudioBitrate)); audio.Add(new XElement("channels", movieFile.MediaInfo.AudioChannels)); audio.Add(new XElement("codec", MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, sceneName))); audio.Add(new XElement("language", movieFile.MediaInfo.AudioLanguages)); streamDetails.Add(audio); if (movieFile.MediaInfo.Subtitles != null && movieFile.MediaInfo.Subtitles.Length > 0) { var subtitle = new XElement("subtitle"); subtitle.Add(new XElement("language", movieFile.MediaInfo.Subtitles)); streamDetails.Add(subtitle); } fileInfo.Add(streamDetails); details.Add(fileInfo); } doc.Add(details); doc.Save(xw); xmlResult += doc.ToString(); xmlResult += Environment.NewLine; } var metadataFileName = GetMovieMetadataFilename(movieFile.RelativePath); if (Settings.UseMovieNfo) { metadataFileName = "movie.nfo"; } return(new MetadataFileResult(metadataFileName, xmlResult.Trim(Environment.NewLine.ToCharArray()))); }
public override MetadataFileResult MovieMetadata(Movie movie, MovieFile movieFile) { var xmlResult = string.Empty; if (Settings.MovieMetadata) { _logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ? (int)movie.OriginalLanguage : Settings.MovieMetadataLanguage; var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage); var isoLanguage = IsoLanguages.Get(selectedSettingsLanguage); var isoLanguageTwoLetterCode = isoLanguage.TwoLetterCode; var countryCode = isoLanguage.CountryCode; if (TmdbClient == null) { TmdbClient = new TMDbClient(Settings.ApiKey) { DefaultCountry = countryCode, DefaultLanguage = isoLanguageTwoLetterCode, ThrowApiExceptions = true }; } var extraMethods = TMDbLibMovies.MovieMethods.Credits | TMDbLibMovies.MovieMethods.Releases | TMDbLibMovies.MovieMethods.Videos; TMDbLibMovies.Movie tmdbMovie = null; try { tmdbMovie = TmdbClient.GetMovieAsync(movie.TmdbId, extraMethods).Result; } catch (Exception exception) { _logger.Error(exception, "Fail to obtain Tmdb Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); } Collection tmdbMovieCollection = null; if (tmdbMovie.BelongsToCollection != null) { try { tmdbMovieCollection = TmdbClient.GetCollectionAsync(tmdbMovie.BelongsToCollection.Id).Result; } catch (Exception exception) { _logger.Error(exception, "Fail to obtain Tmdb Movie Collection Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); } } var sb = new StringBuilder(); var xws = new XmlWriterSettings { OmitXmlDeclaration = false, Encoding = Encoding.UTF8, Indent = false }; if (tmdbMovie != null) { using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); var details = new XElement("movie"); details.Add(new XElement("title", tmdbMovie.Title)); details.Add(new XElement("originaltitle", tmdbMovie.OriginalTitle)); details.Add(new XElement("sorttitle", tmdbMovie.Title.ToLowerInvariant())); if (tmdbMovie.VoteAverage > 0) { var setRating = new XElement("ratings"); var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true")); setRatethemoviedb.Add(new XElement("value", tmdbMovie.VoteAverage)); setRatethemoviedb.Add(new XElement("votes", tmdbMovie.VoteCount)); setRating.Add(setRatethemoviedb); details.Add(setRating); } details.Add(new XElement("rating", tmdbMovie.VoteAverage)); details.Add(new XElement("top250")); var outlineEndPosition = tmdbMovie.Overview.IndexOf(". "); details.Add(new XElement("outline", tmdbMovie.Overview.Substring(0, outlineEndPosition > 0 ? outlineEndPosition + 1 : tmdbMovie.Overview.Length))); details.Add(new XElement("plot", tmdbMovie.Overview)); details.Add(new XElement("tagline", tmdbMovie.Tagline)); details.Add(new XElement("runtime", tmdbMovie.Runtime)); if (tmdbMovie.PosterPath != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.poster), new XAttribute("preview", BaseImageUrl + "/w185" + tmdbMovie.PosterPath), BaseImageUrl + "/original" + tmdbMovie.PosterPath)); } if (Settings.FanartApiKey.IsNotNullOrWhiteSpace()) { string content = null; try { var fanartRequest = new HttpRequest($"http://webservice.fanart.tv/v3/movies/{movie.TmdbId}?api_key={Settings.FanartApiKey}", HttpAccept.Json); var fanartResponse = _client.Execute(fanartRequest); content = fanartResponse.Content; } catch (Exception e) { _logger.Error(e, "Can't obtain data from Fanart for Movie: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); } if (content.IsNotNullOrWhiteSpace()) { var originalLanguageTwoLetterCode = tmdbMovie.OriginalLanguage; var fanartMovie = Json.Deserialize <FanartMovie>(content); if (fanartMovie != null) { var moviebanner = GetBestOptionForFanartMovieArt(fanartMovie.moviebanner, isoLanguageTwoLetterCode, originalLanguageTwoLetterCode); if (moviebanner != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.banner), new XAttribute("preview", moviebanner.url.Replace("/fanart/", "/preview/")), moviebanner.url)); } var hdmovieclearart = GetBestOptionForFanartMovieArt(fanartMovie.hdmovieclearart, isoLanguageTwoLetterCode, originalLanguageTwoLetterCode); if (hdmovieclearart != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.clearart), new XAttribute("preview", hdmovieclearart.url.Replace("/fanart/", "/preview/")), hdmovieclearart.url)); } var hdmovielogo = GetBestOptionForFanartMovieArt(fanartMovie.hdmovielogo, isoLanguageTwoLetterCode, originalLanguageTwoLetterCode); if (hdmovielogo != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.clearlogo), new XAttribute("preview", hdmovielogo.url.Replace("/fanart/", "/preview/")), hdmovielogo.url)); } if (fanartMovie.moviedisc != null) { var moviedisc = GetBestOptionForFanartMovieArt(fanartMovie.moviedisc.Cast <FanartMovieArt>().ToList(), isoLanguageTwoLetterCode, originalLanguageTwoLetterCode); if (moviedisc != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.discart), new XAttribute("preview", moviedisc.url.Replace("/fanart/", "/preview/")), moviedisc.url)); } } var moviethumb = GetBestOptionForFanartMovieArt(fanartMovie.moviethumb, isoLanguageTwoLetterCode, originalLanguageTwoLetterCode); if (moviethumb != null) { details.Add(new XElement("thumb", new XAttribute("aspect", CoverType.landscape), new XAttribute("preview", moviethumb.url.Replace("/fanart/", "/preview/")), moviethumb.url)); } } } } if (tmdbMovie.BackdropPath != null) { details.Add(new XElement("fanart", new XElement("thumb", new XAttribute("preview", BaseImageUrl + "/w300" + tmdbMovie.BackdropPath), BaseImageUrl + "/original" + tmdbMovie.BackdropPath))); } if (tmdbMovie.Releases?.Countries != null) { var releases = tmdbMovie.Releases.Countries.Where(i => !string.IsNullOrWhiteSpace(i.Certification)).ToList(); var ourRelease = releases.FirstOrDefault(c => string.Equals(c.Iso_3166_1, isoLanguageTwoLetterCode, StringComparison.OrdinalIgnoreCase)); var usRelease = releases.FirstOrDefault(c => string.Equals(c.Iso_3166_1, "US", StringComparison.OrdinalIgnoreCase)); if (ourRelease != null) { var ratingPrefix = string.Equals(isoLanguageTwoLetterCode, "US", StringComparison.OrdinalIgnoreCase) ? string.Empty : isoLanguageTwoLetterCode.ToUpperInvariant() + "-"; var newRating = ratingPrefix + ourRelease.Certification.Replace("DE-", "FSK-"); details.Add(new XElement("mpaa", newRating)); } else if (usRelease != null) { details.Add(new XElement("mpaa", usRelease.Certification)); } } var uniqueId = new XElement("uniqueid", tmdbMovie.Id); uniqueId.SetAttributeValue("type", "tmdb"); uniqueId.SetAttributeValue("default", true); details.Add(uniqueId); details.Add(new XElement("tmdbid", tmdbMovie.Id)); if (tmdbMovie.ImdbId.IsNotNullOrWhiteSpace()) { var imdbId = new XElement("uniqueid", tmdbMovie.ImdbId); imdbId.SetAttributeValue("type", "imdb"); details.Add(imdbId); details.Add(new XElement("imdbid", tmdbMovie.ImdbId)); } foreach (var genre in tmdbMovie.Genres) { details.Add(new XElement("genre", genre.Name)); } foreach (var country in tmdbMovie.ProductionCountries) { details.Add(new XElement("country", country.Name)); } if (tmdbMovieCollection != null) { details.Add(new XElement("collectionnumber", tmdbMovieCollection.Id)); var setElement = new XElement("set"); setElement.SetAttributeValue("tmdbcolid", tmdbMovieCollection.Id); setElement.Add(new XElement("name", tmdbMovieCollection.Name)); setElement.Add(new XElement("overview", tmdbMovieCollection.Overview)); details.Add(setElement); } foreach (var writer in tmdbMovie.Credits.Crew.Where(crew => (crew.Job == "Screenplay" || crew.Job == "Story" || crew.Job == "Novel" || crew.Job == "Writer") && crew.Name.IsNotNullOrWhiteSpace())) { details.Add(new XElement("credits", writer.Name)); } foreach (var director in tmdbMovie.Credits.Crew.Where(crew => crew.Job == "Director" && crew.Name.IsNotNullOrWhiteSpace())) { details.Add(new XElement("director", director.Name)); } if (tmdbMovie.ReleaseDate.HasValue) { details.Add(new XElement("releasedate", tmdbMovie.ReleaseDate.Value.ToString("yyyy-MM-dd"))); details.Add(new XElement("premiered", tmdbMovie.ReleaseDate.Value.ToString("yyyy-MM-dd"))); details.Add(new XElement("year", tmdbMovie.ReleaseDate.Value.Year)); } details.Add(new XElement("status", tmdbMovie.Status)); foreach (var company in tmdbMovie.ProductionCompanies) { details.Add(new XElement("studio", company.Name)); } details.Add(new XElement("trailer", GetYoutubeTrailer(tmdbMovie))); if (movieFile.MediaInfo != null) { var sceneName = movieFile.GetSceneOrFileName(); var fileInfo = new XElement("fileinfo"); var streamDetails = new XElement("streamdetails"); var video = new XElement("video"); video.Add(new XElement("aspect", movieFile.MediaInfo.Width / movieFile.MediaInfo.Height)); video.Add(new XElement("bitrate", movieFile.MediaInfo.VideoBitrate)); video.Add(new XElement("codec", MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, sceneName))); video.Add(new XElement("framerate", movieFile.MediaInfo.VideoFps)); video.Add(new XElement("height", movieFile.MediaInfo.Height)); video.Add(new XElement("scantype", movieFile.MediaInfo.ScanType)); video.Add(new XElement("width", movieFile.MediaInfo.Width)); if (movieFile.MediaInfo.RunTime != default) { video.Add(new XElement("duration", movieFile.MediaInfo.RunTime.TotalMinutes)); video.Add(new XElement("durationinseconds", Math.Round(movieFile.MediaInfo.RunTime.TotalSeconds))); } streamDetails.Add(video); var audio = new XElement("audio"); var audioChannelCount = movieFile.MediaInfo.AudioChannels; audio.Add(new XElement("bitrate", movieFile.MediaInfo.AudioBitrate)); audio.Add(new XElement("channels", audioChannelCount)); audio.Add(new XElement("codec", MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, sceneName))); audio.Add(new XElement("language", movieFile.MediaInfo.AudioLanguages)); streamDetails.Add(audio); if (movieFile.MediaInfo.Subtitles != null && movieFile.MediaInfo.Subtitles.Count > 0) { var subtitle = new XElement("subtitle"); subtitle.Add(new XElement("language", movieFile.MediaInfo.Subtitles)); streamDetails.Add(subtitle); } fileInfo.Add(streamDetails); details.Add(fileInfo); foreach (var cast in tmdbMovie.Credits.Cast) { if (cast.Name.IsNotNullOrWhiteSpace() && cast.Character.IsNotNullOrWhiteSpace()) { var actorElement = new XElement("actor"); actorElement.Add(new XElement("name", cast.Name)); actorElement.Add(new XElement("role", cast.Character)); actorElement.Add(new XElement("order", cast.Order)); if (cast.ProfilePath.IsNotNullOrWhiteSpace()) { actorElement.Add(new XElement("thumb", BaseImageUrl + "/original" + cast.ProfilePath)); } details.Add(actorElement); } } details.Add(new XElement("dateadded", movieFile.DateAdded.ToString("s"))); } doc.Add(details); doc.Save(xw); xmlResult += doc.ToString(); xmlResult += Environment.NewLine; } } } if (Settings.MovieMetadataURL) { xmlResult += "https://www.themoviedb.org/movie/" + movie.TmdbId; xmlResult += Environment.NewLine; xmlResult += "https://www.imdb.com/title/" + movie.ImdbId; xmlResult += Environment.NewLine; } var metadataFileName = GetMovieMetadataFilename(movieFile.RelativePath); return(string.IsNullOrEmpty(xmlResult) ? null : new MetadataFileResult(metadataFileName, xmlResult.Trim(Environment.NewLine.ToCharArray()))); }
public override MetadataFileResult MovieMetadata(Movie movie, MovieFile movieFile) { var xmlResult = string.Empty; if (Settings.MovieMetadata) { _logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ? (int)movie.OriginalLanguage : Settings.MovieMetadataLanguage; var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id); var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage); var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage); var credits = _creditService.GetAllCreditsForMovie(movie.Id); var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath); var sb = new StringBuilder(); var xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; xws.Indent = false; using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot); var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster); var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart); var details = new XElement("movie"); details.Add(new XElement("title", movieTranslation?.Title ?? movie.Title)); details.Add(new XElement("originaltitle", movie.OriginalTitle)); details.Add(new XElement("sorttitle", movie.SortTitle)); if (movie.Ratings != null && movie.Ratings.Votes > 0) { var setRating = new XElement("ratings"); var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true")); setRatethemoviedb.Add(new XElement("value", movie.Ratings.Value)); setRatethemoviedb.Add(new XElement("votes", movie.Ratings.Votes)); setRating.Add(setRatethemoviedb); details.Add(setRating); } if (movie.Ratings != null && movie.Ratings.Votes > 0) { details.Add(new XElement("rating", movie.Ratings.Value)); } details.Add(new XElement("userrating")); details.Add(new XElement("top250")); details.Add(new XElement("outline")); details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.Overview)); details.Add(new XElement("tagline")); details.Add(new XElement("runtime", movie.Runtime)); if (thumbnail != null) { details.Add(new XElement("thumb", thumbnail.Url)); } foreach (var poster in posters) { if (poster != null && poster.Url != null) { details.Add(new XElement("thumb", new XAttribute("aspect", "poster"), new XAttribute("preview", poster.Url), poster.Url)); } } if (fanarts.Any()) { var fanartElement = new XElement("fanart"); foreach (var fanart in fanarts) { if (fanart != null && fanart.Url != null) { fanartElement.Add(new XElement("thumb", new XAttribute("preview", fanart.Url), fanart.Url)); } } details.Add(fanartElement); } if (movie.Certification.IsNotNullOrWhiteSpace()) { details.Add(new XElement("mpaa", movie.Certification)); } details.Add(new XElement("playcount")); details.Add(new XElement("lastplayed")); details.Add(new XElement("id", movie.TmdbId)); var uniqueId = new XElement("uniqueid", movie.TmdbId); uniqueId.SetAttributeValue("type", "tmdb"); uniqueId.SetAttributeValue("default", true); details.Add(uniqueId); if (movie.ImdbId.IsNotNullOrWhiteSpace()) { var imdbId = new XElement("uniqueid", movie.ImdbId); imdbId.SetAttributeValue("type", "imdb"); details.Add(imdbId); } foreach (var genre in movie.Genres) { details.Add(new XElement("genre", genre)); } details.Add(new XElement("country")); if (movie.Collection?.Name != null) { var setElement = new XElement("set"); setElement.Add(new XElement("name", movie.Collection.Name)); setElement.Add(new XElement("overview")); details.Add(setElement); } foreach (var tag in movie.Tags) { details.Add(new XElement("tag", tag)); } foreach (var credit in credits) { if (credit.Name != null && credit.Job == "Screenplay") { details.Add(new XElement("credits", credit.Name)); } } foreach (var credit in credits) { if (credit.Name != null && credit.Job == "Director") { details.Add(new XElement("director", credit.Name)); } } if (movie.InCinemas.HasValue) { details.Add(new XElement("premiered", movie.InCinemas.Value.ToString("yyyy-MM-dd"))); } details.Add(new XElement("year", movie.Year)); details.Add(new XElement("studio", movie.Studio)); details.Add(new XElement("trailer", "https://www.youtube.com/watch?v=" + movie.YouTubeTrailerId)); if (movieFile.MediaInfo != null) { var sceneName = movieFile.GetSceneOrFileName(); var fileInfo = new XElement("fileinfo"); var streamDetails = new XElement("streamdetails"); var video = new XElement("video"); video.Add(new XElement("aspect", (float)movieFile.MediaInfo.Width / (float)movieFile.MediaInfo.Height)); video.Add(new XElement("bitrate", movieFile.MediaInfo.VideoBitrate)); video.Add(new XElement("codec", MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, sceneName))); video.Add(new XElement("framerate", movieFile.MediaInfo.VideoFps)); video.Add(new XElement("height", movieFile.MediaInfo.Height)); video.Add(new XElement("scantype", movieFile.MediaInfo.ScanType)); video.Add(new XElement("width", movieFile.MediaInfo.Width)); if (movieFile.MediaInfo.RunTime != null) { video.Add(new XElement("duration", movieFile.MediaInfo.RunTime.TotalMinutes)); video.Add(new XElement("durationinseconds", movieFile.MediaInfo.RunTime.TotalSeconds)); } streamDetails.Add(video); var audio = new XElement("audio"); var audioChannelCount = movieFile.MediaInfo.AudioChannelsStream > 0 ? movieFile.MediaInfo.AudioChannelsStream : movieFile.MediaInfo.AudioChannelsContainer; audio.Add(new XElement("bitrate", movieFile.MediaInfo.AudioBitrate)); audio.Add(new XElement("channels", audioChannelCount)); audio.Add(new XElement("codec", MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, sceneName))); audio.Add(new XElement("language", movieFile.MediaInfo.AudioLanguages)); streamDetails.Add(audio); if (movieFile.MediaInfo.Subtitles != null && movieFile.MediaInfo.Subtitles.Length > 0) { var subtitle = new XElement("subtitle"); subtitle.Add(new XElement("language", movieFile.MediaInfo.Subtitles)); streamDetails.Add(subtitle); } fileInfo.Add(streamDetails); details.Add(fileInfo); foreach (var credit in credits) { if (credit.Name != null && credit.Character != null) { var actorElement = new XElement("actor"); actorElement.Add(new XElement("name", credit.Name)); actorElement.Add(new XElement("role", credit.Character)); actorElement.Add(new XElement("order", credit.Order)); var headshot = credit.Images.FirstOrDefault(m => m.CoverType == MediaCoverTypes.Headshot); if (headshot != null && headshot.Url != null) { actorElement.Add(new XElement("thumb", headshot.Url)); } details.Add(actorElement); } } } doc.Add(details); doc.Save(xw); xmlResult += doc.ToString(); xmlResult += Environment.NewLine; } } if (Settings.MovieMetadataURL) { xmlResult += "https://www.themoviedb.org/movie/" + movie.TmdbId; xmlResult += Environment.NewLine; xmlResult += "https://www.imdb.com/title/" + movie.ImdbId; xmlResult += Environment.NewLine; } var metadataFileName = GetMovieMetadataFilename(movieFile.RelativePath); return(string.IsNullOrEmpty(xmlResult) ? null : new MetadataFileResult(metadataFileName, xmlResult.Trim(Environment.NewLine.ToCharArray()))); }
private void AddMediaInfoTokens(Dictionary <string, Func <TokenMatch, string> > tokenHandlers, MovieFile movieFile) { if (movieFile.MediaInfo == null) { return; } var sceneName = movieFile.GetSceneOrFileName(); var videoCodec = MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, sceneName); var audioCodec = MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, sceneName); var audioChannels = MediaInfoFormatter.FormatAudioChannels(movieFile.MediaInfo); // Workaround until https://github.com/MediaArea/MediaInfo/issues/299 is fixed and release if (audioCodec.EqualsIgnoreCase("DTS-X")) { audioChannels = audioChannels - 1 + 0.1m; } var mediaInfoAudioLanguages = GetLanguagesToken(movieFile.MediaInfo.AudioLanguages); if (!mediaInfoAudioLanguages.IsNullOrWhiteSpace()) { mediaInfoAudioLanguages = $"[{mediaInfoAudioLanguages}]"; } var mediaInfoAudioLanguagesAll = mediaInfoAudioLanguages; if (mediaInfoAudioLanguages == "[EN]") { mediaInfoAudioLanguages = string.Empty; } var mediaInfoSubtitleLanguages = GetLanguagesToken(movieFile.MediaInfo.Subtitles); if (!mediaInfoSubtitleLanguages.IsNullOrWhiteSpace()) { mediaInfoSubtitleLanguages = $"[{mediaInfoSubtitleLanguages}]"; } var videoBitDepth = movieFile.MediaInfo.VideoBitDepth > 0 ? movieFile.MediaInfo.VideoBitDepth.ToString() : string.Empty; var audioChannelsFormatted = audioChannels > 0 ? audioChannels.ToString("F1", CultureInfo.InvariantCulture) : string.Empty; var mediaInfo3D = movieFile.MediaInfo.VideoMultiViewCount > 1 ? "3D" : string.Empty; var videoColourPrimaries = movieFile.MediaInfo.VideoColourPrimaries ?? string.Empty; var videoTransferCharacteristics = movieFile.MediaInfo.VideoTransferCharacteristics ?? string.Empty; var mediaInfoHDR = string.Empty; if (movieFile.MediaInfo.VideoBitDepth >= 10 && !videoColourPrimaries.IsNullOrWhiteSpace() && !videoTransferCharacteristics.IsNullOrWhiteSpace()) { string[] validTransferFunctions = new string[] { "PQ", "HLG" }; if (videoColourPrimaries.EqualsIgnoreCase("BT.2020") && validTransferFunctions.Any(videoTransferCharacteristics.Contains)) { mediaInfoHDR = "HDR"; } } tokenHandlers["{MediaInfo Video}"] = m => videoCodec; tokenHandlers["{MediaInfo VideoCodec}"] = m => videoCodec; tokenHandlers["{MediaInfo VideoBitDepth}"] = m => videoBitDepth; tokenHandlers["{MediaInfo Audio}"] = m => audioCodec; tokenHandlers["{MediaInfo AudioCodec}"] = m => audioCodec; tokenHandlers["{MediaInfo AudioChannels}"] = m => audioChannelsFormatted; tokenHandlers["{MediaInfo AudioLanguages}"] = m => mediaInfoAudioLanguages; tokenHandlers["{MediaInfo AudioLanguagesAll}"] = m => mediaInfoAudioLanguagesAll; tokenHandlers["{MediaInfo SubtitleLanguages}"] = m => mediaInfoSubtitleLanguages; tokenHandlers["{MediaInfo 3D}"] = m => mediaInfo3D; tokenHandlers["{MediaInfo HDR}"] = m => mediaInfoHDR; tokenHandlers["{MediaInfo Simple}"] = m => $"{videoCodec} {audioCodec}"; tokenHandlers["{MediaInfo Full}"] = m => $"{videoCodec} {audioCodec}{mediaInfoAudioLanguages} {mediaInfoSubtitleLanguages}"; }