From 4556524f7e3ba07aab54fb71a828573594a59ac2 Mon Sep 17 00:00:00 2001
From: rlauu <46294892+rlauu@users.noreply.github.com>
Date: Thu, 18 Apr 2024 18:08:35 +0200
Subject: [PATCH] Refactor BaseItemAnalyzerTask and add Edl support for credits
---
.../Data/EdlAction.cs | 5 ++
.../EdlManager.cs | 38 +++++++++---
.../Entrypoint.cs | 46 ++++++---------
.../QueueManager.cs | 32 ++++++----
.../ScheduledTasks/BaseItemAnalyzerTask.cs | 59 ++++++++-----------
.../ScheduledTasks/DetectCreditsTask.cs | 4 +-
.../ScheduledTasks/DetectIntrosCreditsTask.cs | 12 +---
.../ScheduledTasks/DetectIntrosTask.cs | 4 +-
8 files changed, 104 insertions(+), 96 deletions(-)
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Data/EdlAction.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Data/EdlAction.cs
index 5ae2aa9..159e950 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/Data/EdlAction.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/Data/EdlAction.cs
@@ -34,4 +34,9 @@ public enum EdlAction
/// Show a skip button.
///
Intro,
+
+ ///
+ /// Show a skip button.
+ ///
+ Credit,
}
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/EdlManager.cs b/ConfusedPolarBear.Plugin.IntroSkipper/EdlManager.cs
index 0620c78..3f5ff66 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/EdlManager.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/EdlManager.cs
@@ -63,14 +63,12 @@ public static class EdlManager
{
var id = episode.EpisodeId;
- if (!Plugin.Instance!.Intros.TryGetValue(id, out var intro))
+ bool hasIntro = Plugin.Instance!.Intros.TryGetValue(id, out var intro) && intro.Valid;
+ bool hasCredit = Plugin.Instance!.Credits.TryGetValue(id, out var credit) && credit.Valid;
+
+ if (!hasIntro && !hasCredit)
{
- _logger?.LogDebug("Episode {Id} did not have an introduction, skipping", id);
- continue;
- }
- else if (!intro.Valid)
- {
- _logger?.LogDebug("Episode {Id} did not have a valid introduction, skipping", id);
+ _logger?.LogDebug("Episode {Id} has neither a valid intro nor credit, skipping", id);
continue;
}
@@ -84,7 +82,31 @@ public static class EdlManager
continue;
}
- File.WriteAllText(edlPath, intro.ToEdl(action));
+ var edlContent = string.Empty;
+
+ if (hasIntro)
+ {
+ edlContent += intro?.ToEdl(action);
+ }
+
+ if (hasCredit)
+ {
+ if (edlContent.Length > 0)
+ {
+ edlContent += Environment.NewLine;
+ }
+
+ if (action == EdlAction.Intro)
+ {
+ edlContent += credit?.ToEdl(EdlAction.Credit);
+ }
+ else
+ {
+ edlContent += credit?.ToEdl(action);
+ }
+ }
+
+ File.WriteAllText(edlPath, edlContent);
}
}
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Entrypoint.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Entrypoint.cs
index 6b5b501..311e69c 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/Entrypoint.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/Entrypoint.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -259,45 +261,33 @@ public class Entrypoint : IServerEntryPoint
var progress = new Progress();
var cancellationToken = _cancellationTokenSource.Token;
+ var modes = new List();
+ var tasklogger = _loggerFactory.CreateLogger("DefaultLogger");
+
if (Plugin.Instance!.Configuration.AutoDetectIntros && Plugin.Instance!.Configuration.AutoDetectCredits)
{
- // This is where we can optimize a single scan
- var baseIntroAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Introduction,
- _loggerFactory.CreateLogger(),
- _loggerFactory,
- _libraryManager);
-
- baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
-
- var baseCreditAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Credits,
- _loggerFactory.CreateLogger(),
- _loggerFactory,
- _libraryManager);
-
- baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
+ modes.Add(AnalysisMode.Introduction);
+ modes.Add(AnalysisMode.Credits);
+ tasklogger = _loggerFactory.CreateLogger();
}
else if (Plugin.Instance!.Configuration.AutoDetectIntros)
{
- var baseIntroAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Introduction,
- _loggerFactory.CreateLogger(),
- _loggerFactory,
- _libraryManager);
-
- baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
+ modes.Add(AnalysisMode.Introduction);
+ tasklogger = _loggerFactory.CreateLogger();
}
else if (Plugin.Instance!.Configuration.AutoDetectCredits)
{
- var baseCreditAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Credits,
- _loggerFactory.CreateLogger(),
+ modes.Add(AnalysisMode.Credits);
+ tasklogger = _loggerFactory.CreateLogger();
+ }
+
+ var baseCreditAnalyzer = new BaseItemAnalyzerTask(
+ modes.AsReadOnly(),
+ tasklogger,
_loggerFactory,
_libraryManager);
- baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
- }
+ baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
}
Plugin.Instance!.Configuration.PathRestrictions.Clear();
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs b/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs
index 564d631..4c123df 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs
@@ -231,17 +231,16 @@ public class QueueManager
/// This is done to ensure that we don't analyze items that were deleted between the call to GetMediaItems() and popping them from the queue.
///
/// Queued media items.
- /// Analysis mode.
+ /// Analysis mode.
/// Media items that have been verified to exist in Jellyfin and in storage.
- public (ReadOnlyCollection VerifiedItems, bool AnyUnanalyzed)
- VerifyQueue(ReadOnlyCollection candidates, AnalysisMode mode)
+ public (ReadOnlyCollection VerifiedItems, ReadOnlyCollection RequiredModes)
+ VerifyQueue(ReadOnlyCollection candidates, ReadOnlyCollection modes)
{
- var unanalyzed = false;
var verified = new List();
+ var reqModes = new List();
- var timestamps = mode == AnalysisMode.Introduction ?
- Plugin.Instance!.Intros :
- Plugin.Instance!.Credits;
+ var requiresIntroAnalysis = modes.Contains(AnalysisMode.Introduction);
+ var requiresCreditsAnalysis = modes.Contains(AnalysisMode.Credits);
foreach (var candidate in candidates)
{
@@ -252,24 +251,31 @@ public class QueueManager
if (File.Exists(path))
{
verified.Add(candidate);
- }
- if (!timestamps.ContainsKey(candidate.EpisodeId))
- {
- unanalyzed = true;
+ if (requiresIntroAnalysis && !Plugin.Instance!.Intros.ContainsKey(candidate.EpisodeId))
+ {
+ reqModes.Add(AnalysisMode.Introduction);
+ requiresIntroAnalysis = false; // No need to check again
+ }
+
+ if (requiresCreditsAnalysis && !Plugin.Instance!.Credits.ContainsKey(candidate.EpisodeId))
+ {
+ reqModes.Add(AnalysisMode.Credits);
+ requiresCreditsAnalysis = false; // No need to check again
+ }
}
}
catch (Exception ex)
{
_logger.LogDebug(
"Skipping {Mode} analysis of {Name} ({Id}): {Exception}",
- mode,
+ modes,
candidate.Name,
candidate.EpisodeId,
ex);
}
}
- return (verified.AsReadOnly(), unanalyzed);
+ return (verified.AsReadOnly(), reqModes.AsReadOnly());
}
}
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/BaseItemAnalyzerTask.cs b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/BaseItemAnalyzerTask.cs
index 3eabd6d..9161383 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/BaseItemAnalyzerTask.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/BaseItemAnalyzerTask.cs
@@ -1,6 +1,7 @@
namespace ConfusedPolarBear.Plugin.IntroSkipper;
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
@@ -12,7 +13,7 @@ using Microsoft.Extensions.Logging;
///
public class BaseItemAnalyzerTask
{
- private readonly AnalysisMode _analysisMode;
+ private readonly ReadOnlyCollection _analysisModes;
private readonly ILogger _logger;
@@ -23,22 +24,22 @@ public class BaseItemAnalyzerTask
///
/// Initializes a new instance of the class.
///
- /// Analysis mode.
+ /// Analysis mode.
/// Task logger.
/// Logger factory.
/// Library manager.
public BaseItemAnalyzerTask(
- AnalysisMode mode,
+ ReadOnlyCollection modes,
ILogger logger,
ILoggerFactory loggerFactory,
ILibraryManager libraryManager)
{
- _analysisMode = mode;
+ _analysisModes = modes;
_logger = logger;
_loggerFactory = loggerFactory;
_libraryManager = libraryManager;
- if (mode == AnalysisMode.Introduction)
+ if (Plugin.Instance!.Configuration.EdlAction != EdlAction.None)
{
EdlManager.Initialize(_logger);
}
@@ -79,7 +80,7 @@ public class BaseItemAnalyzerTask
"No episodes to analyze. If you are limiting the list of libraries to analyze, check that all library names have been spelled correctly.");
}
- if (this._analysisMode == AnalysisMode.Introduction)
+ if (Plugin.Instance!.Configuration.EdlAction != EdlAction.None)
{
EdlManager.LogConfiguration();
}
@@ -96,9 +97,9 @@ public class BaseItemAnalyzerTask
// Since the first run of the task can run for multiple hours, ensure that none
// of the current media items were deleted from Jellyfin since the task was started.
- var (episodes, unanalyzed) = queueManager.VerifyQueue(
+ var (episodes, requiredModes) = queueManager.VerifyQueue(
season.Value.AsReadOnly(),
- this._analysisMode);
+ _analysisModes);
if (episodes.Count == 0)
{
@@ -107,7 +108,7 @@ public class BaseItemAnalyzerTask
var first = episodes[0];
- if (!unanalyzed)
+ if (requiredModes.Count == 0)
{
_logger.LogDebug(
"All episodes in {Name} season {Season} have already been analyzed",
@@ -124,10 +125,13 @@ public class BaseItemAnalyzerTask
return;
}
- var analyzed = AnalyzeItems(episodes, cancellationToken);
- Interlocked.Add(ref totalProcessed, analyzed);
+ foreach (AnalysisMode mode in requiredModes)
+ {
+ var analyzed = AnalyzeItems(episodes, mode, cancellationToken);
+ Interlocked.Add(ref totalProcessed, analyzed);
- writeEdl = analyzed > 0 || Plugin.Instance!.Configuration.RegenerateEdlFiles;
+ writeEdl = analyzed > 0 || Plugin.Instance!.Configuration.RegenerateEdlFiles;
+ }
}
catch (FingerprintException ex)
{
@@ -138,34 +142,15 @@ public class BaseItemAnalyzerTask
ex);
}
- if (
- writeEdl &&
- Plugin.Instance!.Configuration.EdlAction != EdlAction.None &&
- _analysisMode == AnalysisMode.Introduction)
+ if (writeEdl && Plugin.Instance!.Configuration.EdlAction != EdlAction.None)
{
EdlManager.UpdateEDLFiles(episodes);
}
- if (_logger is ILogger)
- {
- if (_analysisMode == AnalysisMode.Introduction)
- {
- progress.Report(((totalProcessed * 100) / totalQueued) / 2);
- }
- else
- {
- progress.Report((((totalProcessed * 100) / totalQueued) / 2) + 50);
- }
- }
- else
- {
- progress.Report((totalProcessed * 100) / totalQueued);
- }
+ progress.Report((totalProcessed * 100) / totalQueued);
});
- if (
- _analysisMode == AnalysisMode.Introduction &&
- Plugin.Instance!.Configuration.RegenerateEdlFiles)
+ if (Plugin.Instance!.Configuration.RegenerateEdlFiles)
{
_logger.LogInformation("Turning EDL file regeneration flag off");
Plugin.Instance!.Configuration.RegenerateEdlFiles = false;
@@ -177,10 +162,12 @@ public class BaseItemAnalyzerTask
/// Analyze a group of media items for skippable segments.
///
/// Media items to analyze.
+ /// Analysis mode.
/// Cancellation token.
/// Number of items that were successfully analyzed.
private int AnalyzeItems(
ReadOnlyCollection items,
+ AnalysisMode mode,
CancellationToken cancellationToken)
{
var totalItems = items.Count;
@@ -206,7 +193,7 @@ public class BaseItemAnalyzerTask
analyzers.Add(new ChromaprintAnalyzer(_loggerFactory.CreateLogger()));
}
- if (this._analysisMode == AnalysisMode.Credits)
+ if (mode == AnalysisMode.Credits)
{
analyzers.Add(new BlackFrameAnalyzer(_loggerFactory.CreateLogger()));
}
@@ -215,7 +202,7 @@ public class BaseItemAnalyzerTask
// analyzed items from the queue.
foreach (var analyzer in analyzers)
{
- items = analyzer.AnalyzeMediaFiles(items, this._analysisMode, cancellationToken);
+ items = analyzer.AnalyzeMediaFiles(items, mode, cancellationToken);
}
return totalItems;
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectCreditsTask.cs b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectCreditsTask.cs
index c2d71c7..b7b17e4 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectCreditsTask.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectCreditsTask.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
@@ -87,9 +88,10 @@ public class DetectCreditsTask : IScheduledTask
_logger.LogInformation("Scheduled Task is starting");
Plugin.Instance!.Configuration.PathRestrictions.Clear();
+ var modes = new List { AnalysisMode.Credits };
var baseCreditAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Credits,
+ modes.AsReadOnly(),
_loggerFactory.CreateLogger(),
_loggerFactory,
_libraryManager);
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosCreditsTask.cs b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosCreditsTask.cs
index 925d5c0..aea91ab 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosCreditsTask.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosCreditsTask.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
@@ -86,23 +87,16 @@ public class DetectIntrosCreditsTask : IScheduledTask
_logger.LogInformation("Scheduled Task is starting");
Plugin.Instance!.Configuration.PathRestrictions.Clear();
+ var modes = new List { AnalysisMode.Introduction, AnalysisMode.Credits };
var baseIntroAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Introduction,
+ modes.AsReadOnly(),
_loggerFactory.CreateLogger(),
_loggerFactory,
_libraryManager);
baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
- var baseCreditAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Credits,
- _loggerFactory.CreateLogger(),
- _loggerFactory,
- _libraryManager);
-
- baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
-
ScheduledTaskSemaphore.Release();
return Task.CompletedTask;
}
diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosTask.cs b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosTask.cs
index d6afc35..1ba8900 100644
--- a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosTask.cs
+++ b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/DetectIntrosTask.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
@@ -86,9 +87,10 @@ public class DetectIntrosTask : IScheduledTask
_logger.LogInformation("Scheduled Task is starting");
Plugin.Instance!.Configuration.PathRestrictions.Clear();
+ var modes = new List { AnalysisMode.Introduction };
var baseIntroAnalyzer = new BaseItemAnalyzerTask(
- AnalysisMode.Introduction,
+ modes.AsReadOnly(),
_loggerFactory.CreateLogger(),
_loggerFactory,
_libraryManager);