public void CustomFormatMappingTest() { var customorder = new Order { BurnInLogo = false, BurnInSubtitles = false, DestinationFormat = StateFormat.h264_od_standard, DestinationPath = "\\\\ondnas01\\MediaCache\\Test\\WfsJob\\Marvin", DueDate = DateTime.Now, FilePath = "\\\\ondnas01\\MediaCache\\Test\\detkommernaermere.dif", LogoPath = "", Priority = Priority.medium, SubtitlesPath = "", CallbackUrl = "http://some/system", }; _videoMediaFileMetadata = new MediaInfoResult { Video = new Video { CodecId = "custom42", DisplayAspectRatioRawValue = 16f / 9f, Width = 640 } }; mockMediaInfoFacade.Setup(m => m.Read(It.IsAny <string>())) .Returns(_videoMediaFileMetadata); customorder.Validate(mockMediaInfoFacade.Object, mockTimeProvider.Object); var source = MappingHelper.GetSource(customorder); Assert.That(source.Format, Is.EqualTo(StateFormat.custom)); Assert.That(source.CustomFormat, Is.EqualTo("custom42")); }
public static MediaInfoResult GetMediaInfo(string fileName, bool forceRefresh) { MediaInfoResult vidInfo = new MediaInfoResult(); MediaInfoReader.ReadMediaInfo(fileName, forceRefresh, ref vidInfo); return(vidInfo); }
public void NullResponseFromMediaInfoThrowsCorrectOrderException() { _videoMediaFileMetadata = null; mockMediaInfoFacade.Setup(m => m.Read(It.Is <string>(x => !x.EndsWith("wav")))).Returns(_videoMediaFileMetadata); var ex = Assert.Throws <OrderException>(() => sut.Validate(mockMediaInfoFacade.Object, mockTimeProvider.Object)); Assert.That(ex.Message, Is.EqualTo("File is not a valid media file. Source file must be dv5p or xd5c for video or wma, mpeg or pcm for audio format or wav for alternate audio.")); }
/// <summary> /// Fetches the WTV info. /// </summary> /// <param name="video">The video.</param> /// <param name="data">The data.</param> private void FetchWtvInfo(Video video, MediaInfoResult data) { if (data.format == null || data.format.tags == null) { return; } if (!video.LockedFields.Contains(MetadataFields.Genres)) { var genres = GetDictionaryValue(data.format.tags, "genre"); if (!string.IsNullOrEmpty(genres)) { video.Genres = genres.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) .Select(i => i.Trim()) .ToList(); } } var overview = GetDictionaryValue(data.format.tags, "WM/SubTitleDescription"); if (!string.IsNullOrWhiteSpace(overview)) { video.Overview = overview; } var officialRating = GetDictionaryValue(data.format.tags, "WM/ParentalRating"); if (!string.IsNullOrWhiteSpace(officialRating)) { video.OfficialRating = officialRating; } var people = GetDictionaryValue(data.format.tags, "WM/MediaCredits"); if (!string.IsNullOrEmpty(people)) { video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) .Select(i => new PersonInfo { Name = i.Trim(), Type = PersonType.Actor }) .ToList(); } var year = GetDictionaryValue(data.format.tags, "WM/OriginalReleaseTime"); if (!string.IsNullOrWhiteSpace(year)) { int val; if (int.TryParse(year, NumberStyles.Integer, UsCulture, out val)) { video.ProductionYear = val; } } }
/// <summary> /// Get all the hash info and video/audio info for a video file /// </summary> /// <param name="fileName"></param> /// <param name="hashInfo"></param> /// <param name="vidInfo"></param> public static void GetVideoInfo(string fileName, ref Hashes hashInfo, ref MediaInfoResult vidInfo, bool forceRefresh) { hashInfo = Hasher.CalculateHashes(fileName, null); if (vidInfo == null) { vidInfo = new MediaInfoResult(); } MediaInfoReader.ReadMediaInfo(fileName, forceRefresh, ref vidInfo); }
/// <summary> /// Adds the chapters. /// </summary> /// <param name="result">The result.</param> /// <param name="standardError">The standard error.</param> private void AddChapters(MediaInfoResult result, string standardError) { var lines = standardError.Split('\n').Select(l => l.TrimStart()); var chapters = new List <ChapterInfo>(); ChapterInfo lastChapter = null; foreach (var line in lines) { if (line.StartsWith("Chapter", StringComparison.OrdinalIgnoreCase)) { // Example: // Chapter #0.2: start 400.534, end 4565.435 const string srch = "start "; var start = line.IndexOf(srch, StringComparison.OrdinalIgnoreCase); if (start == -1) { continue; } var subString = line.Substring(start + srch.Length); subString = subString.Substring(0, subString.IndexOf(',')); double seconds; if (double.TryParse(subString, NumberStyles.Any, UsCulture, out seconds)) { lastChapter = new ChapterInfo { StartPositionTicks = TimeSpan.FromSeconds(seconds).Ticks }; chapters.Add(lastChapter); } } else if (line.StartsWith("title", StringComparison.OrdinalIgnoreCase)) { if (lastChapter != null && string.IsNullOrEmpty(lastChapter.Name)) { var index = line.IndexOf(':'); if (index != -1) { lastChapter.Name = line.Substring(index + 1).Trim().TrimEnd('\r'); } } } } result.Chapters = chapters; }
public void Setup() { mockMediaInfoFacade = new Mock <IMediaInfoFacade>(MockBehavior.Strict); _videoMediaFileMetadata = new MediaInfoResult { Duration = 42, Video = new Video { CodecId = "xd5c", DisplayAspectRatioRawValue = 16f / 9f, Width = 640 }, Audio = new Audio { Format = "pcm", Channel = "2" } }; _audioMediaFileMetadata = new MediaInfoResult { Duration = 42, Audio = new Audio { Format = "mpeg_audio", Channel = "2" } }; ObjectFactory.Configure(configure => configure.For <IMediaInfoFacade>().Use(mockMediaInfoFacade.Object)); mockTimeProvider.Setup(m => m.GetUtcNow()).Returns(DateTime.Now); ObjectFactory.Configure(configure => configure.For <ITimeProvider>().Use(mockTimeProvider.Object)); sut = new Order { BurnInLogo = true, BurnInSubtitles = false, DestinationFormat = StateFormat.h264_od_single, DestinationPath = "\\\\ondnas01\\MediaCache\\Test\\WfsJob\\Marvin", DueDate = mockTimeProvider.Object.GetUtcNow(), FilePath = "\\\\ondnas01\\MediaCache\\Test\\detkommernaermere.dif", LogoPath = @"\\ondnas01\MediaCache\Test\pepe30.png", AlternateAudioPath = "\\\\ondnas01\\MediaCache\\Test\\WavFileTest.wav", Priority = Priority.medium, SubtitlesPath = "", CallbackUrl = "http://some/system", DestinationFilename = "destinationFilename" }; mockMediaInfoFacade.Setup(m => m.Read(It.Is <string>(x => x.EndsWith("wav")))).Returns(_audioMediaFileMetadata); mockMediaInfoFacade.Setup(m => m.Read(It.Is <string>(x => !x.EndsWith("wav")))).Returns(_videoMediaFileMetadata); }
private static void ValidateAudioInVideo(MediaInfoResult mi) { if (mi?.Audio == null) { return; } var audioStream = mi.Audio; //TODO: Reject unsupported audio //if (!Enum.IsDefined(typeof(StateFormat),audioStream.Format)) // throw new OrderException("Audio is not in a valid format."); var allowedChannelCount = new[] { "1" }; if (Array.Exists(allowedChannelCount, element => element.Equals(audioStream.Channel))) { throw new OrderException("Only audio with more than 1 channel is supported."); } }
/// <summary> /// Fetches the specified video. /// </summary> /// <param name="video">The video.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> protected async Task Fetch(Video video, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) { if (data.format != null) { // For dvd's this may not always be accurate, so don't set the runtime if the item already has one var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0; if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration)) { video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, UsCulture)).Ticks; } } if (data.streams != null) { video.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) .Where(i => i != null) .ToList(); } var chapters = data.Chapters ?? new List <ChapterInfo>(); if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) { var inputPath = isoMount != null ? isoMount.MountedPath : video.Path; FetchBdInfo(video, chapters, inputPath, cancellationToken); } AddExternalSubtitles(video); FetchWtvInfo(video, data); if (chapters.Count == 0 && video.MediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); } await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false); await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false); }
/// <summary> /// Fetches the specified audio. /// </summary> /// <param name="audio">The audio.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> protected void Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data) { if (data.streams == null) { Logger.Error("Audio item has no streams: " + audio.Path); return; } audio.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) .Where(i => i != null) .ToList(); // Get the first audio stream var stream = data.streams.FirstOrDefault(s => s.codec_type.Equals("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.tags != null) { FetchDataFromTags(audio, data.format.tags); } }
/// <summary> /// Normalizes the FF probe result. /// </summary> /// <param name="result">The result.</param> protected void NormalizeFFProbeResult(MediaInfoResult result) { if (result.format != null && result.format.tags != null) { result.format.tags = ConvertDictionaryToCaseInSensitive(result.format.tags); } if (result.streams != null) { // Convert all dictionaries to case insensitive foreach (var stream in result.streams) { if (stream.tags != null) { stream.tags = ConvertDictionaryToCaseInSensitive(stream.tags); } if (stream.disposition != null) { stream.disposition = ConvertDictionaryToCaseInSensitive(stream.disposition); } } } }
public override void ProcessCommand() { logger.Info("Reading Media Info for File: {0}", VideoLocalID); try { VideoLocalRepository repVids = new VideoLocalRepository(); VideoLocal vlocal = repVids.GetByID(VideoLocalID); if (vlocal == null) { logger.Error("Cound not find Video: {0}", VideoLocalID); return; } if (!File.Exists(vlocal.FullServerPath)) { logger.Error("Cound not find physical file: {0}", vlocal.FullServerPath); return; } int nshareID = -1; VideoInfoRepository repVidInfo = new VideoInfoRepository(); VideoInfo vinfo = repVidInfo.GetByHash(vlocal.Hash); ImportFolderRepository repNS = new ImportFolderRepository(); List <ImportFolder> shares = repNS.GetAll(); string fileName = vlocal.FullServerPath; string filePath = ""; DataAccessHelper.GetShareAndPath(fileName, shares, ref nshareID, ref filePath); FileInfo fi = new FileInfo(fileName); if (vinfo == null) { vinfo = new VideoInfo(); vinfo.Hash = vlocal.Hash; vinfo.Duration = 0; vinfo.FileSize = fi.Length; vinfo.DateTimeUpdated = DateTime.Now; vinfo.FileName = filePath; vinfo.AudioBitrate = ""; vinfo.AudioCodec = ""; vinfo.VideoBitrate = ""; vinfo.VideoBitDepth = ""; vinfo.VideoCodec = ""; vinfo.VideoFrameRate = ""; vinfo.VideoResolution = ""; } logger.Trace("Getting media info for: {0}", fileName); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(fileName, true); vinfo.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; vinfo.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; vinfo.DateTimeUpdated = vlocal.DateTimeUpdated; vinfo.Duration = mInfo.Duration; vinfo.FileName = filePath; vinfo.FileSize = fi.Length; vinfo.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; vinfo.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; vinfo.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; vinfo.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; vinfo.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; vinfo.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repVidInfo.Save(vinfo); } catch (Exception ex) { logger.Error("Error processing CommandRequest_ReadMediaInfo: {0} - {1}", VideoLocalID, ex.ToString()); return; } }
public static Media GenerateMediaFromVideoLocal(VideoLocal v) { VideoInfo info = v.VideoInfo; Media m = null; if (info != null) { if (!string.IsNullOrEmpty(info.FullInfo)) { try { m = XmlDeserializeFromString <Media>(info.FullInfo); } catch (Exception) { info.FullInfo = null; } } if (string.IsNullOrEmpty(info.FullInfo)) { try { VideoInfoRepository repo = new VideoInfoRepository(); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true); info.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; info.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; info.Duration = mInfo.Duration; info.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; info.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; info.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; info.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; info.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repo.Save(info); m = XmlDeserializeFromString <Media>(info.FullInfo); } catch (Exception) { //FILE DO NOT EXIST } } } if (m != null) { m.Id = v.VideoLocalID.ToString(); List <Stream> subs = SubtitleHelper.GetSubtitleStreams(v.FullServerPath); if (subs.Count > 0) { m.Parts[0].Streams.AddRange(subs); } foreach (Part p in m.Parts) { p.Id = null; p.Accessible = "1"; p.Exists = "1"; bool vid = false; bool aud = false; bool txt = false; foreach (Stream ss in p.Streams.ToArray()) { if ((ss.StreamType == "1") && !vid) { vid = true; } if ((ss.StreamType == "2") && !aud) { aud = true; ss.Selected = "1"; } if ((ss.StreamType == "3") && !txt) { txt = true; ss.Selected = "1"; } } } } return(m); }
private static void PopulateVideoEpisodeFromVideoLocal(Video l, VideoLocal v, JMMType type) { l.Type = "episode"; l.Summary = "Episode Overview Not Available"; l.Title = Path.GetFileNameWithoutExtension(v.FilePath); l.Key = l.PrimaryExtraKey = ServerUrl(int.Parse(ServerSettings.JMMServerPort), MainWindow.PathAddressKodi + "/GetMetadata/0/" + (int)type + "/" + v.VideoLocalID); l.AddedAt = v.DateTimeCreated.Year.ToString("0000") + "-" + v.DateTimeCreated.Month.ToString("00") + "-" + v.DateTimeCreated.Day.ToString("00") + " " + v.DateTimeCreated.Hour.ToString("00") + ":" + v.DateTimeCreated.Minute.ToString("00") + ":" + v.DateTimeCreated.Millisecond.ToString("00"); l.UpdatedAt = v.DateTimeUpdated.Year.ToString("0000") + "-" + v.DateTimeUpdated.Month.ToString("00") + "-" + v.DateTimeUpdated.Day.ToString("00") + " " + v.DateTimeUpdated.Hour.ToString("00") + ":" + v.DateTimeUpdated.Minute.ToString("00") + ":" + v.DateTimeUpdated.Millisecond.ToString("00"); l.OriginallyAvailableAt = v.DateTimeCreated.Year.ToString("0000") + "-" + v.DateTimeCreated.Month.ToString("00") + "-" + v.DateTimeCreated.Day.ToString("00"); l.Year = v.DateTimeCreated.Year.ToString(); VideoInfo info = v.VideoInfo; Media m = null; if (info != null) { if (!string.IsNullOrEmpty(info.FullInfo)) { try { m = XmlDeserializeFromString <Media>(info.FullInfo); } catch (Exception) { info.FullInfo = null; } } if (string.IsNullOrEmpty(info.FullInfo)) { VideoInfoRepository repo = new VideoInfoRepository(); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true, true); info.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; info.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; info.Duration = mInfo.Duration; info.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; info.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; info.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; info.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; info.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repo.Save(info); m = XmlDeserializeFromString <Media>(info.FullInfo); } } l.Medias = new List <Media>(); if (m != null) { m.Id = null; List <JMMContracts.KodiContracts.Stream> subs = SubtitleHelper.GetSubtitleStreamsKodi(v.FullServerPath); if (subs.Count > 0) { foreach (JMMContracts.KodiContracts.Stream s in subs) { s.Key = ServerUrl(int.Parse(ServerSettings.JMMServerFilePort), "file/0/" + Base64EncodeUrl(s.File), KodiObject.IsExternalRequest); } m.Parts[0].Streams.AddRange(subs); } foreach (Part p in m.Parts) { p.Id = null; p.File = v.FullServerPath; string ff = Path.GetExtension(v.FullServerPath); p.Key = ServerUrl(int.Parse(ServerSettings.JMMServerFilePort), "videolocal/0/" + v.VideoLocalID + "/file" + ff, KodiObject.IsExternalRequest); p.Accessible = "1"; p.Exists = "1"; bool vid = false; bool aud = false; bool txt = false; foreach (JMMContracts.KodiContracts.Stream ss in p.Streams.ToArray()) { if ((ss.StreamType == "1") && (!vid)) { vid = true; } if ((ss.StreamType == "2") && (!aud)) { aud = true; ss.Selected = "1"; } if ((ss.StreamType == "3") && (!txt)) { txt = true; ss.Selected = "1"; } } } l.Medias.Add(m); l.Duration = m.Duration; } }
public static bool ReadMediaInfo(string fileNameFull, bool forceRefresh, ref MediaInfoResult info) { return(ReadMediaInfo(fileNameFull, forceRefresh, ref info, false)); }
private static void PopulateVideoEpisodeFromVideoLocal(Video l, VideoLocal v, JMMType type, int userid) { l.Type = "episode"; l.Summary = "Episode Overview Not Available"; //TODO Intenationalization l.Title = Path.GetFileNameWithoutExtension(v.FilePath); l.Key = ContructVideoLocalIdUrl(userid, v.VideoLocalID, type); l.AddedAt = v.DateTimeCreated.ToUnixTime(); l.UpdatedAt = v.DateTimeUpdated.ToUnixTime(); l.OriginallyAvailableAt = v.DateTimeCreated.ToPlexDate(); l.Year = v.DateTimeCreated.Year.ToString(); VideoInfo info = v.VideoInfo; Media m = null; if (info != null) { if (!string.IsNullOrEmpty(info.FullInfo)) { try { m = XmlDeserializeFromString <Media>(info.FullInfo); } catch (Exception) { info.FullInfo = null; } } if (string.IsNullOrEmpty(info.FullInfo)) { VideoInfoRepository repo = new VideoInfoRepository(); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(v.FullServerPath, true); info.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; info.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; info.Duration = mInfo.Duration; info.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; info.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; info.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; info.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; info.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; info.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repo.Save(info); m = XmlDeserializeFromString <Media>(info.FullInfo); } } l.Medias = new List <Media>(); if (m != null) { m.Id = null; List <JMMContracts.PlexContracts.Stream> subs = SubtitleHelper.GetSubtitleStreams(v.FullServerPath); if (subs.Count > 0) { foreach (JMMContracts.PlexContracts.Stream s in subs) { s.Key = ConstructFileStream(userid, s.File); } m.Parts[0].Streams.AddRange(subs); } foreach (Part p in m.Parts) { p.Id = null; string ff = Path.GetExtension(v.FullServerPath); p.Key = ConstructVideoLocalStream(userid, v.VideoLocalID, ff); p.Accessible = "1"; p.Exists = "1"; bool vid = false; bool aud = false; bool txt = false; foreach (JMMContracts.PlexContracts.Stream ss in p.Streams.ToArray()) { if ((ss.StreamType == "1") && (!vid)) { vid = true; } if ((ss.StreamType == "2") && (!aud)) { aud = true; ss.Selected = "1"; } if ((ss.StreamType == "3") && (!txt)) { txt = true; ss.Selected = "1"; } } } l.Medias.Add(m); l.Duration = m.Duration; } }
public static bool ReadMediaInfo(string fileNameFull, bool forceRefresh, ref MediaInfoResult info) { try { if (!forceRefresh) { // if we have populated the full info, we have already read the data if (!string.IsNullOrEmpty(info.FullInfo)) { return(false); } } Media m = PlexMediaInfo.MediaConvert.Convert(fileNameFull); if (m != null) { string xml = XmlSerializeToString(m); if (!string.IsNullOrEmpty(m.Width) && !string.IsNullOrEmpty(m.Height)) { info.VideoResolution = m.Width + "x" + m.Height; } if (!string.IsNullOrEmpty(m.VideoCodec)) { info.VideoCodec = m.VideoCodec; } if (!string.IsNullOrEmpty(m.AudioCodec)) { info.AudioCodec = m.AudioCodec; } if (!string.IsNullOrEmpty(m.Duration)) { info.Duration = int.Parse(m.Duration); } List <JMMContracts.PlexContracts.Stream> vparts = m.Parts[0].Streams.Where(a => a.StreamType == "1").ToList(); if (vparts.Count > 0) { if (!string.IsNullOrEmpty(vparts[0].Bitrate)) { info.VideoBitrate = vparts[0].Bitrate; } if (!string.IsNullOrEmpty(vparts[0].BitDepth)) { info.VideoBitDepth = vparts[0].BitDepth; } if (!string.IsNullOrEmpty(vparts[0].FrameRate)) { info.VideoFrameRate = vparts[0].FrameRate; } } List <JMMContracts.PlexContracts.Stream> aparts = m.Parts[0].Streams.Where(a => a.StreamType == "2").ToList(); if (aparts.Count > 0) { if (!string.IsNullOrEmpty(aparts[0].Bitrate)) { info.AudioBitrate = aparts[0].Bitrate; } } info.FullInfo = xml; } else { logger.Error("ERROR getting media info:: {0}", fileNameFull); } } catch (Exception ex) { logger.Error("Error reading Media Info for: {0} --- {1}", fileNameFull, ex.ToString()); } return(true); }
private VideoLocal ProcessFile_LocalInfo() { // hash and read media info for file int nshareID = -1; string filePath = ""; ImportFolderRepository repNS = new ImportFolderRepository(); List <ImportFolder> shares = repNS.GetAll(); DataAccessHelper.GetShareAndPath(FileName, shares, ref nshareID, ref filePath); if (!File.Exists(FileName)) { logger.Error("File does not exist: {0}", FileName); return(null); } int numAttempts = 0; // Wait 3 minutes seconds before giving up on trying to access the file while ((!CanAccessFile(FileName)) && (numAttempts < 180)) { numAttempts++; Thread.Sleep(1000); Console.WriteLine("Attempt # " + numAttempts.ToString()); } // if we failed to access the file, get ouuta here if (numAttempts == 180) { logger.Error("Could not access file: " + FileName); return(null); } // check if we have already processed this file VideoLocal vlocal = null; VideoLocalRepository repVidLocal = new VideoLocalRepository(); FileNameHashRepository repFNHash = new FileNameHashRepository(); List <VideoLocal> vidLocals = repVidLocal.GetByFilePathAndShareID(filePath, nshareID); FileInfo fi = new FileInfo(FileName); if (vidLocals.Count > 0) { vlocal = vidLocals[0]; logger.Trace("VideoLocal record found in database: {0}", vlocal.VideoLocalID); if (ForceHash) { vlocal.FileSize = fi.Length; vlocal.DateTimeUpdated = DateTime.Now; } } else { logger.Trace("VideoLocal, creating new record"); vlocal = new VideoLocal(); vlocal.DateTimeUpdated = DateTime.Now; vlocal.DateTimeCreated = vlocal.DateTimeUpdated; vlocal.FilePath = filePath; vlocal.FileSize = fi.Length; vlocal.ImportFolderID = nshareID; vlocal.Hash = ""; vlocal.CRC32 = ""; vlocal.MD5 = ""; vlocal.SHA1 = ""; vlocal.IsIgnored = 0; vlocal.IsVariation = 0; } // check if we need to get a hash this file Hashes hashes = null; if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash) { // try getting the hash from the CrossRef if (!ForceHash) { CrossRef_File_EpisodeRepository repCrossRefs = new CrossRef_File_EpisodeRepository(); List <CrossRef_File_Episode> crossRefs = repCrossRefs.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (crossRefs.Count == 1) { vlocal.Hash = crossRefs[0].Hash; vlocal.HashSource = (int)HashSource.DirectHash; } } // try getting the hash from the LOCAL cache if (!ForceHash && string.IsNullOrEmpty(vlocal.Hash)) { List <FileNameHash> fnhashes = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (fnhashes != null && fnhashes.Count > 1) { // if we have more than one record it probably means there is some sort of corruption // lets delete the local records foreach (FileNameHash fnh in fnhashes) { repFNHash.Delete(fnh.FileNameHashID); } } if (fnhashes != null && fnhashes.Count == 1) { logger.Trace("Got hash from LOCAL cache: {0} ({1})", FileName, fnhashes[0].Hash); vlocal.Hash = fnhashes[0].Hash; vlocal.HashSource = (int)HashSource.WebCacheFileName; } } // hash the file if (string.IsNullOrEmpty(vlocal.Hash) || ForceHash) { DateTime start = DateTime.Now; logger.Trace("Calculating hashes for: {0}", FileName); // update the VideoLocal record with the Hash hashes = FileHashHelper.GetHashInfo(FileName, true, MainWindow.OnHashProgress, ServerSettings.Hash_CRC32, ServerSettings.Hash_MD5, ServerSettings.Hash_SHA1); TimeSpan ts = DateTime.Now - start; logger.Trace("Hashed file in {0} seconds --- {1} ({2})", ts.TotalSeconds.ToString("#0.0"), FileName, Utils.FormatByteSize(vlocal.FileSize)); vlocal.Hash = hashes.ed2k; vlocal.CRC32 = hashes.crc32; vlocal.MD5 = hashes.md5; vlocal.SHA1 = hashes.sha1; vlocal.HashSource = (int)HashSource.DirectHash; } // We should have a hash by now // before we save it, lets make sure there is not any other record with this hash (possible duplicate file) VideoLocal vidTemp = repVidLocal.GetByHash(vlocal.Hash); if (vidTemp != null) { // don't delete it, if it is actually the same record if (vidTemp.VideoLocalID != vlocal.VideoLocalID) { // delete the VideoLocal record logger.Warn("Deleting duplicate video file record"); logger.Warn("---------------------------------------------"); logger.Warn("Keeping record for: {0}", vlocal.FullServerPath); logger.Warn("Deleting record for: {0}", vidTemp.FullServerPath); logger.Warn("---------------------------------------------"); // check if we have a record of this in the database, if not create one DuplicateFileRepository repDups = new DuplicateFileRepository(); List <DuplicateFile> dupFiles = repDups.GetByFilePathsAndImportFolder(vlocal.FilePath, vidTemp.FilePath, vlocal.ImportFolderID, vidTemp.ImportFolderID); if (dupFiles.Count == 0) { dupFiles = repDups.GetByFilePathsAndImportFolder(vidTemp.FilePath, vlocal.FilePath, vidTemp.ImportFolderID, vlocal.ImportFolderID); } if (dupFiles.Count == 0) { DuplicateFile dup = new DuplicateFile(); dup.DateTimeUpdated = DateTime.Now; dup.FilePathFile1 = vlocal.FilePath; dup.FilePathFile2 = vidTemp.FilePath; dup.ImportFolderIDFile1 = vlocal.ImportFolderID; dup.ImportFolderIDFile2 = vidTemp.ImportFolderID; dup.Hash = vlocal.Hash; repDups.Save(dup); } repVidLocal.Delete(vidTemp.VideoLocalID); } } repVidLocal.Save(vlocal); // also save the filename to hash record // replace the existing records just in case it was corrupt FileNameHash fnhash = null; List <FileNameHash> fnhashes2 = repFNHash.GetByFileNameAndSize(Path.GetFileName(vlocal.FilePath), vlocal.FileSize); if (fnhashes2 != null && fnhashes2.Count > 1) { // if we have more than one record it probably means there is some sort of corruption // lets delete the local records foreach (FileNameHash fnh in fnhashes2) { repFNHash.Delete(fnh.FileNameHashID); } } if (fnhashes2 != null && fnhashes2.Count == 1) { fnhash = fnhashes2[0]; } else { fnhash = new FileNameHash(); } fnhash.FileName = Path.GetFileName(vlocal.FilePath); fnhash.FileSize = vlocal.FileSize; fnhash.Hash = vlocal.Hash; fnhash.DateTimeUpdated = DateTime.Now; repFNHash.Save(fnhash); } // now check if we have stored a VideoInfo record bool refreshMediaInfo = false; VideoInfoRepository repVidInfo = new VideoInfoRepository(); VideoInfo vinfo = repVidInfo.GetByHash(vlocal.Hash); if (vinfo == null) { refreshMediaInfo = true; vinfo = new VideoInfo(); vinfo.Hash = vlocal.Hash; vinfo.Duration = 0; vinfo.FileSize = fi.Length; vinfo.DateTimeUpdated = DateTime.Now; vinfo.FileName = filePath; vinfo.AudioBitrate = ""; vinfo.AudioCodec = ""; vinfo.VideoBitrate = ""; vinfo.VideoBitDepth = ""; vinfo.VideoCodec = ""; vinfo.VideoFrameRate = ""; vinfo.VideoResolution = ""; repVidInfo.Save(vinfo); } else { // check if we need to update the media info if (vinfo.VideoCodec.Trim().Length == 0) { refreshMediaInfo = true; } else { refreshMediaInfo = false; } } if (refreshMediaInfo) { logger.Trace("Getting media info for: {0}", FileName); MediaInfoResult mInfo = FileHashHelper.GetMediaInfo(FileName, true); vinfo.AudioBitrate = string.IsNullOrEmpty(mInfo.AudioBitrate) ? "" : mInfo.AudioBitrate; vinfo.AudioCodec = string.IsNullOrEmpty(mInfo.AudioCodec) ? "" : mInfo.AudioCodec; vinfo.DateTimeUpdated = vlocal.DateTimeUpdated; vinfo.Duration = mInfo.Duration; vinfo.FileName = filePath; vinfo.FileSize = fi.Length; vinfo.VideoBitrate = string.IsNullOrEmpty(mInfo.VideoBitrate) ? "" : mInfo.VideoBitrate; vinfo.VideoBitDepth = string.IsNullOrEmpty(mInfo.VideoBitDepth) ? "" : mInfo.VideoBitDepth; vinfo.VideoCodec = string.IsNullOrEmpty(mInfo.VideoCodec) ? "" : mInfo.VideoCodec; vinfo.VideoFrameRate = string.IsNullOrEmpty(mInfo.VideoFrameRate) ? "" : mInfo.VideoFrameRate; vinfo.VideoResolution = string.IsNullOrEmpty(mInfo.VideoResolution) ? "" : mInfo.VideoResolution; vinfo.FullInfo = string.IsNullOrEmpty(mInfo.FullInfo) ? "" : mInfo.FullInfo; repVidInfo.Save(vinfo); } // now add a command to process the file CommandRequest_ProcessFile cr_procfile = new CommandRequest_ProcessFile(vlocal.VideoLocalID, false); cr_procfile.Save(); return(vlocal); }
/// <summary> /// Fetches the specified video. /// </summary> /// <param name="video">The video.</param> /// <param name="force">if set to <c>true</c> [force].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> protected async Task Fetch(Video video, bool force, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) { if (data.format != null) { // For dvd's this may not always be accurate, so don't set the runtime if the item already has one var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0; if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration)) { video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, UsCulture)).Ticks; } } if (data.streams != null) { video.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format)) .Where(i => i != null) .ToList(); } var chapters = data.Chapters ?? new List <ChapterInfo>(); if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) { var inputPath = isoMount != null ? isoMount.MountedPath : video.Path; FetchBdInfo(video, chapters, inputPath, cancellationToken); } AddExternalSubtitles(video); FetchWtvInfo(video, force, data); video.IsHD = video.MediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270); if (chapters.Count == 0 && video.MediaStreams.Any(i => i.Type == MediaStreamType.Video)) { AddDummyChapters(video, chapters); } await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false); BaseProviderInfo providerInfo; var videoFileChanged = false; if (video.ProviderData.TryGetValue(Id, out providerInfo)) { videoFileChanged = CompareDate(video) > providerInfo.LastRefreshed; } // Only save chapters if forcing, if the video changed, or if there are not already any saved ones if (force || videoFileChanged || _itemRepo.GetChapter(video.Id, 0) == null) { await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false); } }