diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/AnalyzerHelper.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/AnalyzerHelper.cs index 9b2b7f0..d7829de 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/AnalyzerHelper.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/AnalyzerHelper.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using ConfusedPolarBear.Plugin.IntroSkipper.Configuration; using ConfusedPolarBear.Plugin.IntroSkipper.Data; -using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging; namespace ConfusedPolarBear.Plugin.IntroSkipper; @@ -34,41 +34,26 @@ public class AnalyzerHelper /// Analysis mode. /// Modified Intro Timestamps. public Dictionary AdjustIntroTimes( - IReadOnlyList episodes, - IReadOnlyDictionary originalIntros, - AnalysisMode mode) - { - var modifiedIntros = new Dictionary(); - - foreach (var episode in episodes) - { - _logger.LogTrace("Adjusting introduction end time for {Name} ({Id})", episode.Name, episode.EpisodeId); - - if (!originalIntros.TryGetValue(episode.EpisodeId, out var originalIntro)) - { - _logger.LogTrace("{Name} does not have an intro", episode.Name); - continue; - } - - var adjustedIntro = AdjustIntroForEpisode(episode, originalIntro, mode); - modifiedIntros[episode.EpisodeId] = adjustedIntro; - } - - return modifiedIntros; - } + IReadOnlyList episodes, + IReadOnlyDictionary originalIntros, + AnalysisMode mode) + { + return episodes + .Where(episode => originalIntros.TryGetValue(episode.EpisodeId, out var _)) + .ToDictionary( + episode => episode.EpisodeId, + episode => AdjustIntroForEpisode(episode, originalIntros[episode.EpisodeId], mode)); + } private Segment AdjustIntroForEpisode(QueuedEpisode episode, Segment originalIntro, AnalysisMode mode) { - var chapters = GetChaptersWithVirtualEnd(episode); - var adjustedIntro = new Segment(originalIntro); + _logger.LogTrace("{Name} original intro: {Start} - {End}", episode.Name, originalIntro.Start, originalIntro.End); + var adjustedIntro = new Segment(originalIntro); var originalIntroStart = new TimeRange(Math.Max(0, (int)originalIntro.Start - 5), (int)originalIntro.Start + 10); var originalIntroEnd = new TimeRange((int)originalIntro.End - 10, Math.Min(episode.Duration, (int)originalIntro.End + 5)); - _logger.LogTrace("{Name} original intro: {Start} - {End}", episode.Name, originalIntro.Start, originalIntro.End); - - if (!AdjustIntroBasedOnChapters(episode, chapters, adjustedIntro, originalIntroStart, originalIntroEnd) - && mode == AnalysisMode.Introduction) + if (!AdjustIntroBasedOnChapters(episode, adjustedIntro, originalIntroStart, originalIntroEnd) && mode == AnalysisMode.Introduction) { AdjustIntroBasedOnSilence(episode, adjustedIntro, originalIntroEnd); } @@ -76,31 +61,31 @@ public class AnalyzerHelper return adjustedIntro; } - private static List GetChaptersWithVirtualEnd(QueuedEpisode episode) + private bool AdjustIntroBasedOnChapters(QueuedEpisode episode, Segment adjustedIntro, TimeRange originalIntroStart, TimeRange originalIntroEnd) { var chapters = Plugin.Instance?.GetChapters(episode.EpisodeId) ?? []; - chapters.Add(new ChapterInfo { StartPositionTicks = TimeSpan.FromSeconds(episode.Duration).Ticks }); - return chapters; - } + double previousTime = 0; - private bool AdjustIntroBasedOnChapters(QueuedEpisode episode, List chapters, Segment adjustedIntro, TimeRange originalIntroStart, TimeRange originalIntroEnd) - { - foreach (var chapter in chapters) + for (int i = 0; i <= chapters.Count; i++) { - var chapterStartSeconds = TimeSpan.FromTicks(chapter.StartPositionTicks).TotalSeconds; + double currentTime = i < chapters.Count + ? TimeSpan.FromTicks(chapters[i].StartPositionTicks).TotalSeconds + : episode.Duration; - if (originalIntroStart.Start < chapterStartSeconds && chapterStartSeconds < originalIntroStart.End) + if (originalIntroStart.Start < previousTime && previousTime < originalIntroStart.End) { - adjustedIntro.Start = chapterStartSeconds; - _logger.LogTrace("{Name} chapter found close to intro start: {Start}", episode.Name, chapterStartSeconds); + adjustedIntro.Start = previousTime; + _logger.LogTrace("{Name} chapter found close to intro start: {Start}", episode.Name, previousTime); } - if (originalIntroEnd.Start < chapterStartSeconds && chapterStartSeconds < originalIntroEnd.End) + if (originalIntroEnd.Start < currentTime && currentTime < originalIntroEnd.End) { - adjustedIntro.End = chapterStartSeconds; - _logger.LogTrace("{Name} chapter found close to intro end: {End}", episode.Name, chapterStartSeconds); + adjustedIntro.End = currentTime; + _logger.LogTrace("{Name} chapter found close to intro end: {End}", episode.Name, currentTime); return true; } + + previousTime = currentTime; } return false; diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/ChapterAnalyzer.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/ChapterAnalyzer.cs index db23fbe..88a121c 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/ChapterAnalyzer.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/ChapterAnalyzer.cs @@ -52,7 +52,7 @@ public class ChapterAnalyzer(ILogger logger) : IMediaFileAnalyz var skipRange = FindMatchingChapter( episode, - new(Plugin.Instance.GetChapters(episode.EpisodeId)), + Plugin.Instance.GetChapters(episode.EpisodeId), expression, mode); @@ -81,7 +81,7 @@ public class ChapterAnalyzer(ILogger logger) : IMediaFileAnalyz /// Intro object containing skippable time range, or null if no chapter matched. public Segment? FindMatchingChapter( QueuedEpisode episode, - Collection chapters, + IReadOnlyList chapters, string expression, AnalysisMode mode) { diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs index 21981d1..a17c12c 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs @@ -350,7 +350,7 @@ public class Plugin : BasePlugin, IHasWebPages /// /// Item id. /// List of chapters. - internal List GetChapters(Guid id) + internal IReadOnlyList GetChapters(Guid id) { var item = GetItem(id); if (item == null)