/// <summary> /// Extracts the chapter images. /// </summary> /// <param name="video">The video.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="extractImages">if set to <c>true</c> [extract images].</param> /// <param name="saveItem">if set to <c>true</c> [save item].</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> public async Task PopulateChapterImages(Video video, CancellationToken cancellationToken, bool extractImages, bool saveItem) { if (video.Chapters == null) { throw new ArgumentNullException(); } // Can't extract images if there are no video streams if (video.MediaStreams == null || video.MediaStreams.All(m => m.Type != MediaStreamType.Video)) { return; } var changesMade = false; foreach (var chapter in video.Chapters) { var filename = video.Id + "_" + video.DateModified.Ticks + "_" + chapter.StartPositionTicks; var path = VideoImageCache.GetResourcePath(filename, ".jpg"); if (!VideoImageCache.ContainsFilePath(path)) { if (extractImages) { // Disable for now on folder rips if (video.VideoType != VideoType.VideoFile) { continue; } // Add some time for the first chapter to make sure we don't end up with a black image var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); var success = await ExtractImage(GetInputArgument(video), time, path, cancellationToken).ConfigureAwait(false); if (success) { chapter.ImagePath = path; changesMade = true; } } } else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) { chapter.ImagePath = path; changesMade = true; } } if (saveItem && changesMade) { await _kernel.ItemRepository.SaveItem(video, CancellationToken.None).ConfigureAwait(false); } }
/// <summary> /// Extracts the chapter images. /// </summary> /// <param name="video">The video.</param> /// <param name="chapters">The chapters.</param> /// <param name="extractImages">if set to <c>true</c> [extract images].</param> /// <param name="saveChapters">if set to <c>true</c> [save chapters].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> public async Task <bool> PopulateChapterImages(Video video, List <ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) { // Can't extract images if there are no video streams if (video.MediaStreams == null || video.MediaStreams.All(m => m.Type != MediaStreamType.Video)) { return(true); } var success = true; var changesMade = false; var runtimeTicks = video.RunTimeTicks ?? 0; foreach (var chapter in chapters) { if (chapter.StartPositionTicks >= runtimeTicks) { _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); break; } var filename = video.Path + "_" + video.DateModified.Ticks + "_" + chapter.StartPositionTicks; var path = VideoImageCache.GetResourcePath(filename, ".jpg"); if (!File.Exists(path)) { if (extractImages) { if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso) { continue; } if (video.VideoType == VideoType.BluRay) { // Can only extract reliably on single file blurays if (video.PlayableStreamFileNames == null || video.PlayableStreamFileNames.Count != 1) { continue; } } // Add some time for the first chapter to make sure we don't end up with a black image var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); InputType type; var inputPath = MediaEncoderHelpers.GetInputArgument(video, null, out type); try { var parentPath = Path.GetDirectoryName(path); if (!Directory.Exists(parentPath)) { Directory.CreateDirectory(parentPath); } await _encoder.ExtractImage(inputPath, type, video.Video3DFormat, time, path, cancellationToken).ConfigureAwait(false); chapter.ImagePath = path; changesMade = true; } catch { success = false; break; } } } else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) { chapter.ImagePath = path; changesMade = true; } } if (saveChapters && changesMade) { await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false); } return(success); }