diff options
| author | Tim Eisele <Ghost_of_Stone@web.de> | 2025-04-26 14:01:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-26 14:01:12 +0200 |
| commit | df5671263fc8370ae17b7a5d53f06a86de5cbc93 (patch) | |
| tree | 91e703628c257bd07ce943eb9934b63714e92e75 /Emby.Server.Implementations | |
| parent | f35b8dd33d97309e91bafb58db937352e47e4300 (diff) | |
Merge pull request #13847 from Shadowghost/rework-chapter-management
Rework chapter management
Diffstat (limited to 'Emby.Server.Implementations')
6 files changed, 346 insertions, 301 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5bb75e2b9..7b07243da 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -15,6 +15,7 @@ using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Emby.Naming.Common; using Emby.Photos; +using Emby.Server.Implementations.Chapters; using Emby.Server.Implementations.Collections; using Emby.Server.Implementations.Configuration; using Emby.Server.Implementations.Cryptography; @@ -552,7 +553,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton<IUserViewManager, UserViewManager>(); - serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>(); + serviceCollection.AddSingleton<IChapterManager, ChapterManager>(); serviceCollection.AddSingleton<IAuthService, AuthService>(); serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>(); @@ -647,7 +648,7 @@ namespace Emby.Server.Implementations BaseItem.ProviderManager = Resolve<IProviderManager>(); BaseItem.LocalizationManager = Resolve<ILocalizationManager>(); BaseItem.ItemRepository = Resolve<IItemRepository>(); - BaseItem.ChapterRepository = Resolve<IChapterRepository>(); + BaseItem.ChapterManager = Resolve<IChapterManager>(); BaseItem.FileSystem = Resolve<IFileSystem>(); BaseItem.UserDataManager = Resolve<IUserDataManager>(); BaseItem.ChannelManager = Resolve<IChannelManager>(); diff --git a/Emby.Server.Implementations/Chapters/ChapterManager.cs b/Emby.Server.Implementations/Chapters/ChapterManager.cs new file mode 100644 index 000000000..b4daa2a14 --- /dev/null +++ b/Emby.Server.Implementations/Chapters/ChapterManager.cs @@ -0,0 +1,313 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Extensions; +using MediaBrowser.Controller.Chapters; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.Chapters; + +/// <summary> +/// The chapter manager. +/// </summary> +public class ChapterManager : IChapterManager +{ + private readonly IFileSystem _fileSystem; + private readonly ILogger<ChapterManager> _logger; + private readonly IMediaEncoder _encoder; + private readonly IChapterRepository _chapterRepository; + private readonly ILibraryManager _libraryManager; + private readonly IPathManager _pathManager; + + /// <summary> + /// The first chapter ticks. + /// </summary> + private static readonly long _firstChapterTicks = TimeSpan.FromSeconds(15).Ticks; + + /// <summary> + /// Initializes a new instance of the <see cref="ChapterManager"/> class. + /// </summary> + /// <param name="logger">The <see cref="ILogger{ChapterManager}"/>.</param> + /// <param name="fileSystem">The <see cref="IFileSystem"/>.</param> + /// <param name="encoder">The <see cref="IMediaEncoder"/>.</param> + /// <param name="chapterRepository">The <see cref="IChapterRepository"/>.</param> + /// <param name="libraryManager">The <see cref="ILibraryManager"/>.</param> + /// <param name="pathManager">The <see cref="IPathManager"/>.</param> + public ChapterManager( + ILogger<ChapterManager> logger, + IFileSystem fileSystem, + IMediaEncoder encoder, + IChapterRepository chapterRepository, + ILibraryManager libraryManager, + IPathManager pathManager) + { + _logger = logger; + _fileSystem = fileSystem; + _encoder = encoder; + _chapterRepository = chapterRepository; + _libraryManager = libraryManager; + _pathManager = pathManager; + } + + /// <summary> + /// Determines whether [is eligible for chapter image extraction] [the specified video]. + /// </summary> + /// <param name="video">The video.</param> + /// <param name="libraryOptions">The library options for the video.</param> + /// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns> + private bool IsEligibleForChapterImageExtraction(Video video, LibraryOptions libraryOptions) + { + if (video.IsPlaceHolder) + { + return false; + } + + if (libraryOptions is null || !libraryOptions.EnableChapterImageExtraction) + { + return false; + } + + if (video.IsShortcut) + { + return false; + } + + if (!video.IsCompleteMedia) + { + return false; + } + + // Can't extract images if there are no video streams + return video.DefaultVideoStreamIndex.HasValue; + } + + private long GetAverageDurationBetweenChapters(IReadOnlyList<ChapterInfo> chapters) + { + if (chapters.Count < 2) + { + return 0; + } + + long sum = 0; + for (int i = 1; i < chapters.Count; i++) + { + sum += chapters[i].StartPositionTicks - chapters[i - 1].StartPositionTicks; + } + + return sum / chapters.Count; + } + + /// <inheritdoc /> + public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) + { + if (chapters.Count == 0) + { + return true; + } + + var libraryOptions = _libraryManager.GetLibraryOptions(video); + + if (!IsEligibleForChapterImageExtraction(video, libraryOptions)) + { + extractImages = false; + } + + var averageChapterDuration = GetAverageDurationBetweenChapters(chapters); + var threshold = TimeSpan.FromSeconds(1).Ticks; + if (averageChapterDuration < threshold) + { + _logger.LogInformation("Skipping chapter image extraction for {Video} as the average chapter duration {AverageDuration} was lower than the minimum threshold {Threshold}", video.Name, averageChapterDuration, threshold); + extractImages = false; + } + + var success = true; + var changesMade = false; + + var runtimeTicks = video.RunTimeTicks ?? 0; + + var currentImages = GetSavedChapterImages(video, directoryService); + + foreach (var chapter in chapters) + { + if (chapter.StartPositionTicks >= runtimeTicks) + { + _logger.LogInformation("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); + break; + } + + var path = _pathManager.GetChapterImagePath(video, chapter.StartPositionTicks); + + if (!currentImages.Contains(path, StringComparison.OrdinalIgnoreCase)) + { + if (extractImages) + { + cancellationToken.ThrowIfCancellationRequested(); + + try + { + // 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 inputPath = video.Path; + var directoryPath = Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + + var container = video.Container; + var mediaSource = new MediaSourceInfo + { + VideoType = video.VideoType, + IsoType = video.IsoType, + Protocol = video.PathProtocol ?? MediaProtocol.File, + }; + + _logger.LogInformation("Extracting chapter image for {Name} at {Path}", video.Name, inputPath); + var tempFile = await _encoder.ExtractVideoImage(inputPath, container, mediaSource, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); + File.Copy(tempFile, path, true); + + try + { + _fileSystem.DeleteFile(tempFile); + } + catch (IOException ex) + { + _logger.LogError(ex, "Error deleting temporary chapter image encoding file {Path}", tempFile); + } + + chapter.ImagePath = path; + chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); + changesMade = true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(',', video.Path)); + success = false; + break; + } + } + else if (!string.IsNullOrEmpty(chapter.ImagePath)) + { + chapter.ImagePath = null; + changesMade = true; + } + } + else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) + { + chapter.ImagePath = path; + chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); + changesMade = true; + } + else if (libraryOptions?.EnableChapterImageExtraction != true) + { + // We have an image for the current chapter but the user has disabled chapter image extraction -> delete this chapter's image + chapter.ImagePath = null; + changesMade = true; + } + } + + if (saveChapters && changesMade) + { + _chapterRepository.SaveChapters(video.Id, chapters); + } + + DeleteDeadImages(currentImages, chapters); + + return success; + } + + /// <inheritdoc /> + public void SaveChapters(Video video, IReadOnlyList<ChapterInfo> chapters) + { + _chapterRepository.SaveChapters(video.Id, chapters); + } + + /// <inheritdoc /> + public ChapterInfo? GetChapter(Guid baseItemId, int index) + { + return _chapterRepository.GetChapter(baseItemId, index); + } + + /// <inheritdoc /> + public IReadOnlyList<ChapterInfo> GetChapters(Guid baseItemId) + { + return _chapterRepository.GetChapters(baseItemId); + } + + /// <inheritdoc /> + public void DeleteChapterImages(Video video) + { + var path = _pathManager.GetChapterImageFolderPath(video); + try + { + if (Directory.Exists(path)) + { + _logger.LogInformation("Removing chapter images for {Name} [{Id}]", video.Name, video.Id); + Directory.Delete(path, true); + } + } + catch (Exception ex) + { + _logger.LogWarning("Failed to remove chapter image folder for {Item}: {Exception}", video.Id, ex); + } + + _chapterRepository.DeleteChapters(video.Id); + } + + private IReadOnlyList<string> GetSavedChapterImages(Video video, IDirectoryService directoryService) + { + var path = _pathManager.GetChapterImageFolderPath(video); + if (!Directory.Exists(path)) + { + return []; + } + + try + { + return directoryService.GetFilePaths(path); + } + catch (IOException) + { + return []; + } + } + + private void DeleteDeadImages(IEnumerable<string> images, IEnumerable<ChapterInfo> chapters) + { + var existingImages = chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)); + var deadImages = images + .Except(existingImages, StringComparer.OrdinalIgnoreCase) + .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i.AsSpan()), StringComparison.OrdinalIgnoreCase)) + .ToList(); + + foreach (var image in deadImages) + { + _logger.LogDebug("Deleting dead chapter image {Path}", image); + + try + { + _fileSystem.DeleteFile(image!); + } + catch (IOException ex) + { + _logger.LogError(ex, "Error deleting {Path}.", image); + } + } + } +} diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 5b0fc9ef3..9e0a6080d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -17,7 +17,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Trickplay; @@ -51,7 +50,7 @@ namespace Emby.Server.Implementations.Dto private readonly Lazy<ILiveTvManager> _livetvManagerFactory; private readonly ITrickplayManager _trickplayManager; - private readonly IChapterRepository _chapterRepository; + private readonly IChapterManager _chapterManager; public DtoService( ILogger<DtoService> logger, @@ -64,7 +63,7 @@ namespace Emby.Server.Implementations.Dto IMediaSourceManager mediaSourceManager, Lazy<ILiveTvManager> livetvManagerFactory, ITrickplayManager trickplayManager, - IChapterRepository chapterRepository) + IChapterManager chapterManager) { _logger = logger; _libraryManager = libraryManager; @@ -76,7 +75,7 @@ namespace Emby.Server.Implementations.Dto _mediaSourceManager = mediaSourceManager; _livetvManagerFactory = livetvManagerFactory; _trickplayManager = trickplayManager; - _chapterRepository = chapterRepository; + _chapterManager = chapterManager; } private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; @@ -1061,7 +1060,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.Chapters)) { - dto.Chapters = _chapterRepository.GetChapters(item.Id).ToList(); + dto.Chapters = _chapterManager.GetChapters(item.Id).ToList(); } if (options.ContainsField(ItemFields.Trickplay)) diff --git a/Emby.Server.Implementations/Library/PathManager.cs b/Emby.Server.Implementations/Library/PathManager.cs index 83a6df964..dbd2333ff 100644 --- a/Emby.Server.Implementations/Library/PathManager.cs +++ b/Emby.Server.Implementations/Library/PathManager.cs @@ -29,9 +29,9 @@ public class PathManager : IPathManager _appPaths = appPaths; } - private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); + private string SubtitleCachePath => Path.Join(_appPaths.DataPath, "subtitles"); - private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments"); + private string AttachmentCachePath => Path.Join(_appPaths.DataPath, "attachments"); /// <inheritdoc /> public string GetAttachmentPath(string mediaSourceId, string fileName) @@ -67,7 +67,21 @@ public class PathManager : IPathManager var id = item.Id.ToString("D", CultureInfo.InvariantCulture).AsSpan(); return saveWithMedia - ? Path.Combine(item.ContainingFolderPath, Path.ChangeExtension(item.Path, ".trickplay")) + ? Path.Join(item.ContainingFolderPath, Path.ChangeExtension(item.Path, ".trickplay")) : Path.Join(_config.ApplicationPaths.TrickplayPath, id[..2], id); } + + /// <inheritdoc/> + public string GetChapterImageFolderPath(BaseItem item) + { + return Path.Join(item.GetInternalMetadataPath(), "chapters"); + } + + /// <inheritdoc/> + public string GetChapterImagePath(BaseItem item, long chapterPositionTicks) + { + var filename = item.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + "_" + chapterPositionTicks.ToString(CultureInfo.InvariantCulture) + ".jpg"; + + return Path.Join(GetChapterImageFolderPath(item), filename); + } } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs deleted file mode 100644 index ea7896861..000000000 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ /dev/null @@ -1,272 +0,0 @@ -#nullable disable - -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Jellyfin.Extensions; -using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.MediaEncoder -{ - public class EncodingManager : IEncodingManager - { - private readonly IFileSystem _fileSystem; - private readonly ILogger<EncodingManager> _logger; - private readonly IMediaEncoder _encoder; - private readonly IChapterRepository _chapterManager; - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The first chapter ticks. - /// </summary> - private static readonly long _firstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - - public EncodingManager( - ILogger<EncodingManager> logger, - IFileSystem fileSystem, - IMediaEncoder encoder, - IChapterRepository chapterManager, - ILibraryManager libraryManager) - { - _logger = logger; - _fileSystem = fileSystem; - _encoder = encoder; - _chapterManager = chapterManager; - _libraryManager = libraryManager; - } - - /// <summary> - /// Gets the chapter images data path. - /// </summary> - /// <value>The chapter images data path.</value> - private static string GetChapterImagesPath(BaseItem item) - { - return Path.Combine(item.GetInternalMetadataPath(), "chapters"); - } - - /// <summary> - /// Determines whether [is eligible for chapter image extraction] [the specified video]. - /// </summary> - /// <param name="video">The video.</param> - /// <param name="libraryOptions">The library options for the video.</param> - /// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns> - private bool IsEligibleForChapterImageExtraction(Video video, LibraryOptions libraryOptions) - { - if (video.IsPlaceHolder) - { - return false; - } - - if (libraryOptions is null || !libraryOptions.EnableChapterImageExtraction) - { - return false; - } - - if (video.IsShortcut) - { - return false; - } - - if (!video.IsCompleteMedia) - { - return false; - } - - // Can't extract images if there are no video streams - return video.DefaultVideoStreamIndex.HasValue; - } - - private long GetAverageDurationBetweenChapters(IReadOnlyList<ChapterInfo> chapters) - { - if (chapters.Count < 2) - { - return 0; - } - - long sum = 0; - for (int i = 1; i < chapters.Count; i++) - { - sum += chapters[i].StartPositionTicks - chapters[i - 1].StartPositionTicks; - } - - return sum / chapters.Count; - } - - public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) - { - if (chapters.Count == 0) - { - return true; - } - - var libraryOptions = _libraryManager.GetLibraryOptions(video); - - if (!IsEligibleForChapterImageExtraction(video, libraryOptions)) - { - extractImages = false; - } - - var averageChapterDuration = GetAverageDurationBetweenChapters(chapters); - var threshold = TimeSpan.FromSeconds(1).Ticks; - if (averageChapterDuration < threshold) - { - _logger.LogInformation("Skipping chapter image extraction for {Video} as the average chapter duration {AverageDuration} was lower than the minimum threshold {Threshold}", video.Name, averageChapterDuration, threshold); - extractImages = false; - } - - var success = true; - var changesMade = false; - - var runtimeTicks = video.RunTimeTicks ?? 0; - - var currentImages = GetSavedChapterImages(video, directoryService); - - foreach (var chapter in chapters) - { - if (chapter.StartPositionTicks >= runtimeTicks) - { - _logger.LogInformation("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); - break; - } - - var path = GetChapterImagePath(video, chapter.StartPositionTicks); - - if (!currentImages.Contains(path, StringComparison.OrdinalIgnoreCase)) - { - if (extractImages) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - // 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 inputPath = video.Path; - - Directory.CreateDirectory(Path.GetDirectoryName(path)); - - var container = video.Container; - var mediaSource = new MediaSourceInfo - { - VideoType = video.VideoType, - IsoType = video.IsoType, - Protocol = video.PathProtocol.Value, - }; - - var tempFile = await _encoder.ExtractVideoImage(inputPath, container, mediaSource, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); - File.Copy(tempFile, path, true); - - try - { - _fileSystem.DeleteFile(tempFile); - } - catch (IOException ex) - { - _logger.LogError(ex, "Error deleting temporary chapter image encoding file {Path}", tempFile); - } - - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(',', video.Path)); - success = false; - break; - } - } - else if (!string.IsNullOrEmpty(chapter.ImagePath)) - { - chapter.ImagePath = null; - changesMade = true; - } - } - else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) - { - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - else if (libraryOptions?.EnableChapterImageExtraction != true) - { - // We have an image for the current chapter but the user has disabled chapter image extraction -> delete this chapter's image - chapter.ImagePath = null; - changesMade = true; - } - } - - if (saveChapters && changesMade) - { - _chapterManager.SaveChapters(video.Id, chapters); - } - - DeleteDeadImages(currentImages, chapters); - - return success; - } - - private string GetChapterImagePath(Video video, long chapterPositionTicks) - { - var filename = video.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + "_" + chapterPositionTicks.ToString(CultureInfo.InvariantCulture) + ".jpg"; - - return Path.Combine(GetChapterImagesPath(video), filename); - } - - private static IReadOnlyList<string> GetSavedChapterImages(Video video, IDirectoryService directoryService) - { - var path = GetChapterImagesPath(video); - if (!Directory.Exists(path)) - { - return Array.Empty<string>(); - } - - try - { - return directoryService.GetFilePaths(path); - } - catch (IOException) - { - return Array.Empty<string>(); - } - } - - private void DeleteDeadImages(IEnumerable<string> images, IEnumerable<ChapterInfo> chapters) - { - var deadImages = images - .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) - .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i.AsSpan()), StringComparison.OrdinalIgnoreCase)) - .ToList(); - - foreach (var image in deadImages) - { - _logger.LogDebug("Deleting dead chapter image {Path}", image); - - try - { - _fileSystem.DeleteFile(image); - } - catch (IOException ex) - { - _logger.LogError(ex, "Error deleting {Path}.", image); - } - } - } - } -} diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 563e90fbe..b76fdeeb0 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -11,8 +11,6 @@ using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; @@ -28,42 +26,34 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks { private readonly ILogger<ChapterImagesTask> _logger; private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; private readonly IApplicationPaths _appPaths; - private readonly IEncodingManager _encodingManager; + private readonly IChapterManager _chapterManager; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; - private readonly IChapterRepository _chapterRepository; /// <summary> /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class. /// </summary> /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> - /// <param name="itemRepo">Instance of the <see cref="IItemRepository"/> interface.</param> /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param> - /// <param name="encodingManager">Instance of the <see cref="IEncodingManager"/> interface.</param> + /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> - /// <param name="chapterRepository">Instance of the <see cref="IChapterRepository"/> interface.</param> public ChapterImagesTask( ILogger<ChapterImagesTask> logger, ILibraryManager libraryManager, - IItemRepository itemRepo, IApplicationPaths appPaths, - IEncodingManager encodingManager, + IChapterManager chapterManager, IFileSystem fileSystem, - ILocalizationManager localization, - IChapterRepository chapterRepository) + ILocalizationManager localization) { _logger = logger; _libraryManager = libraryManager; - _itemRepo = itemRepo; _appPaths = appPaths; - _encodingManager = encodingManager; + _chapterManager = chapterManager; _fileSystem = fileSystem; _localization = localization; - _chapterRepository = chapterRepository; } /// <inheritdoc /> @@ -126,12 +116,12 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (IOException) { - previouslyFailedImages = new List<string>(); + previouslyFailedImages = []; } } else { - previouslyFailedImages = new List<string>(); + previouslyFailedImages = []; } var directoryService = new DirectoryService(_fileSystem); @@ -146,9 +136,9 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks try { - var chapters = _chapterRepository.GetChapters(video.Id); + var chapters = _chapterManager.GetChapters(video.Id); - var success = await _encodingManager.RefreshChapterImages(video, directoryService, chapters, extract, true, cancellationToken).ConfigureAwait(false); + var success = await _chapterManager.RefreshChapterImages(video, directoryService, chapters, extract, true, cancellationToken).ConfigureAwait(false); if (!success) { |
