Add back separate tasks as optional

This commit is contained in:
TwistedUmbrellaX 2024-03-30 18:22:54 -04:00
parent 10e942ab7d
commit 2f05cb70e5
6 changed files with 258 additions and 58 deletions

View File

@ -30,17 +30,12 @@ public class PluginConfiguration : BasePluginConfiguration
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to scan for intros during a scheduled task. /// Gets or sets a value indicating whether to scan for intros during a scheduled task.
/// </summary> /// </summary>
public bool DetectIntros { get; set; } = true; public bool AutoDetectIntros { get; set; } = false;
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to scan for credits during a scheduled task. /// Gets or sets a value indicating whether to scan for credits during a scheduled task.
/// </summary> /// </summary>
public bool DetectCredits { get; set; } = true; public bool AutoDetectCredits { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether to analyze automatically, when new Items are added.
/// </summary>
public bool AutomaticAnalysis { get; set; } = false;
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to analyze season 0. /// Gets or sets a value indicating whether to analyze season 0.

View File

@ -29,40 +29,29 @@
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label"> <label class="emby-checkbox-label">
<input id="DetectIntros" type="checkbox" is="emby-checkbox" /> <input id="AutoDetectIntros" type="checkbox" is="emby-checkbox" />
<span>Detect Introductions</span> <span>Automatically Scan Intros</span>
</label> </label>
<div class="fieldDescription"> <div class="fieldDescription">
This option enables scheduled introduction detection. Your videos will be scanned for introductions during a scheduled task. If enabled, introductions will be automatically analyzed for new media
</div> </div>
</div> </div>
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label"> <label class="emby-checkbox-label">
<input id="DetectCredits" type="checkbox" is="emby-checkbox" /> <input id="AutoDetectCredits" type="checkbox" is="emby-checkbox" />
<span>Detect Credits</span> <span>Automatically Scan Credits</span>
</label> </label>
<div class="fieldDescription"> <div class="fieldDescription">
This option enables scheduled credit detection. Your videos will be scanned for credits during a scheduled task. If enabled, credits will be automatically analyzed for new media
</div> </div>
<div class="fieldDescription"> <div class="fieldDescription">
Note: Selecting neither Intro nor Credit Detection will disable automatic scans. To configure the scheduled task, see <a is="emby-linkbutton" class="button-link" href="scheduledtasks.html">scheduled tasks</a>. Note: Selecting neither Intro nor Credit Detection will disable automatic scans. To configure the scheduled task, see <a is="emby-linkbutton" class="button-link" href="scheduledtasks.html">scheduled tasks</a>.
</div> </div>
</div> </div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="AutomaticAnalysis" type="checkbox" is="emby-checkbox" />
<span>Automatic analysis</span>
</label>
<div class="fieldDescription">
If checked, newly added items will be automatically analyzed.
</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label"> <label class="emby-checkbox-label">
<input id="AnalyzeSeasonZero" type="checkbox" is="emby-checkbox" /> <input id="AnalyzeSeasonZero" type="checkbox" is="emby-checkbox" />
@ -227,7 +216,7 @@
Noise tolerance Noise tolerance
</label> </label>
<input id="SilenceDetectionMaximumNoise" type="number" is="emby-input" min="-90" <input id="SilenceDetectionMaximumNoise" type="number" is="emby-input" min="-90"
max="0" /> max="0" />
<div class="fieldDescription"> <div class="fieldDescription">
Noise tolerance in negative decibels. Noise tolerance in negative decibels.
</div> </div>
@ -238,7 +227,7 @@
Minimum silence duration Minimum silence duration
</label> </label>
<input id="SilenceDetectionMinimumDuration" type="number" is="emby-input" min="0" <input id="SilenceDetectionMinimumDuration" type="number" is="emby-input" min="0"
step="0.01" /> step="0.01" />
<div class="fieldDescription"> <div class="fieldDescription">
Minimum silence duration in seconds before adjusting introduction end time. Minimum silence duration in seconds before adjusting introduction end time.
</div> </div>
@ -248,7 +237,7 @@
<details id="detection"> <details id="detection">
<summary>Process Configuration</summary> <summary>Process Configuration</summary>
<br/> <br />
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label"> <label class="emby-checkbox-label">
<input id="UseChromaprint" type="checkbox" is="emby-checkbox" /> <input id="UseChromaprint" type="checkbox" is="emby-checkbox" />
@ -316,7 +305,7 @@
ffmpeg Threads ffmpeg Threads
</label> </label>
<input id="ProcessThreads" type="number" is="emby-input" min="0" <input id="ProcessThreads" type="number" is="emby-input" min="0"
max="16" /> max="16" />
<div class="fieldDescription"> <div class="fieldDescription">
Number of simultaneous processes to use for ffmpeg operations. Number of simultaneous processes to use for ffmpeg operations.
<br /> <br />
@ -623,9 +612,8 @@
] ]
var booleanConfigurationFields = [ var booleanConfigurationFields = [
"DetectIntros", "AutoDetectIntros",
"DetectCredits", "AutoDetectCredits",
"AutomaticAnalysis",
"AnalyzeSeasonZero", "AnalyzeSeasonZero",
"RegenerateEdlFiles", "RegenerateEdlFiles",
"UseChromaprint", "UseChromaprint",

View File

@ -167,22 +167,40 @@ public class Entrypoint : IHostedService
var progress = new Progress<double>(); var progress = new Progress<double>();
var cancellationToken = new CancellationToken(false); var cancellationToken = new CancellationToken(false);
if (Plugin.Instance!.Configuration.DetectIntros) 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<DetectIntrosCreditsTask>(),
_loggerFactory,
_libraryManager);
baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
var baseCreditAnalyzer = new BaseItemAnalyzerTask(
AnalysisMode.Credits,
_loggerFactory.CreateLogger<DetectIntrosCreditsTask>(),
_loggerFactory,
_libraryManager);
baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
}
else if (Plugin.Instance!.Configuration.AutoDetectIntros)
{ {
var baseIntroAnalyzer = new BaseItemAnalyzerTask( var baseIntroAnalyzer = new BaseItemAnalyzerTask(
AnalysisMode.Introduction, AnalysisMode.Introduction,
_loggerFactory.CreateLogger<DetectIntrosAndCreditsTask>(), _loggerFactory.CreateLogger<DetectIntrosTask>(),
_loggerFactory, _loggerFactory,
_libraryManager); _libraryManager);
baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken); baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
} }
else if (Plugin.Instance!.Configuration.AutoDetectCredits)
if (Plugin.Instance!.Configuration.DetectCredits)
{ {
var baseCreditAnalyzer = new BaseItemAnalyzerTask( var baseCreditAnalyzer = new BaseItemAnalyzerTask(
AnalysisMode.Credits, AnalysisMode.Credits,
_loggerFactory.CreateLogger<DetectIntrosAndCreditsTask>(), _loggerFactory.CreateLogger<DetectCreditsTask>(),
_loggerFactory, _loggerFactory,
_libraryManager); _libraryManager);
@ -229,7 +247,7 @@ public class Entrypoint : IHostedService
/// <inheritdoc /> /// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
if (Plugin.Instance!.Configuration.AutomaticAnalysis) if (Plugin.Instance!.Configuration.AutoDetectIntros || Plugin.Instance!.Configuration.AutoDetectCredits)
{ {
_libraryManager.ItemAdded += OnItemAdded; _libraryManager.ItemAdded += OnItemAdded;
_libraryManager.ItemUpdated += OnItemModified; _libraryManager.ItemUpdated += OnItemModified;

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
namespace ConfusedPolarBear.Plugin.IntroSkipper;
/// <summary>
/// Analyze all television episodes for credits.
/// TODO: analyze all media files.
/// </summary>
public class DetectCreditsTask : IScheduledTask
{
private readonly ILogger<DetectCreditsTask> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly ILibraryManager _libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="DetectCreditsTask"/> class.
/// </summary>
/// <param name="loggerFactory">Logger factory.</param>
/// <param name="libraryManager">Library manager.</param>
/// <param name="logger">Logger.</param>
public DetectCreditsTask(
ILogger<DetectCreditsTask> logger,
ILoggerFactory loggerFactory,
ILibraryManager libraryManager)
{
_logger = logger;
_loggerFactory = loggerFactory;
_libraryManager = libraryManager;
}
/// <summary>
/// Gets the task name.
/// </summary>
public string Name => "Detect Credits";
/// <summary>
/// Gets the task category.
/// </summary>
public string Category => "Intro Skipper";
/// <summary>
/// Gets the task description.
/// </summary>
public string Description => "Analyzes the audio and video of all television episodes to find credits.";
/// <summary>
/// Gets the task key.
/// </summary>
public string Key => "CPBIntroSkipperDetectCredits";
/// <summary>
/// Analyze all episodes in the queue. Only one instance of this task should be run at a time.
/// </summary>
/// <param name="progress">Task progress.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Task.</returns>
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
if (_libraryManager is null)
{
throw new InvalidOperationException("Library manager was null");
}
// abort if analyzer is already running
if (Plugin.Instance!.AnalyzerTaskIsRunning)
{
return Task.CompletedTask;
}
else
{
Plugin.Instance!.AnalyzerTaskIsRunning = true;
}
var baseCreditAnalyzer = new BaseItemAnalyzerTask(
AnalysisMode.Credits,
_loggerFactory.CreateLogger<DetectCreditsTask>(),
_loggerFactory,
_libraryManager);
baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
Plugin.Instance!.AnalyzerTaskIsRunning = false;
return Task.CompletedTask;
}
/// <summary>
/// Get task triggers.
/// </summary>
/// <returns>Task triggers.</returns>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
return Array.Empty<TaskTriggerInfo>();
}
}

View File

@ -11,18 +11,18 @@ namespace ConfusedPolarBear.Plugin.IntroSkipper;
/// <summary> /// <summary>
/// Analyze all television episodes for introduction sequences. /// Analyze all television episodes for introduction sequences.
/// </summary> /// </summary>
public class DetectIntrosAndCreditsTask : IScheduledTask public class DetectIntrosCreditsTask : IScheduledTask
{ {
private readonly ILoggerFactory _loggerFactory; private readonly ILoggerFactory _loggerFactory;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DetectIntrosAndCreditsTask"/> class. /// Initializes a new instance of the <see cref="DetectIntrosCreditsTask"/> class.
/// </summary> /// </summary>
/// <param name="loggerFactory">Logger factory.</param> /// <param name="loggerFactory">Logger factory.</param>
/// <param name="libraryManager">Library manager.</param> /// <param name="libraryManager">Library manager.</param>
public DetectIntrosAndCreditsTask( public DetectIntrosCreditsTask(
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
ILibraryManager libraryManager) ILibraryManager libraryManager)
{ {
@ -73,27 +73,21 @@ public class DetectIntrosAndCreditsTask : IScheduledTask
Plugin.Instance!.AnalyzerTaskIsRunning = true; Plugin.Instance!.AnalyzerTaskIsRunning = true;
} }
if (Plugin.Instance!.Configuration.DetectIntros) var baseIntroAnalyzer = new BaseItemAnalyzerTask(
{ AnalysisMode.Introduction,
var baseIntroAnalyzer = new BaseItemAnalyzerTask( _loggerFactory.CreateLogger<DetectIntrosCreditsTask>(),
AnalysisMode.Introduction, _loggerFactory,
_loggerFactory.CreateLogger<DetectIntrosAndCreditsTask>(), _libraryManager);
_loggerFactory,
_libraryManager);
baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken); baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
}
if (Plugin.Instance!.Configuration.DetectCredits) var baseCreditAnalyzer = new BaseItemAnalyzerTask(
{ AnalysisMode.Credits,
var baseCreditAnalyzer = new BaseItemAnalyzerTask( _loggerFactory.CreateLogger<DetectIntrosCreditsTask>(),
AnalysisMode.Credits, _loggerFactory,
_loggerFactory.CreateLogger<DetectIntrosAndCreditsTask>(), _libraryManager);
_loggerFactory,
_libraryManager);
baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken); baseCreditAnalyzer.AnalyzeItems(progress, cancellationToken);
}
Plugin.Instance!.AnalyzerTaskIsRunning = false; Plugin.Instance!.AnalyzerTaskIsRunning = false;

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
namespace ConfusedPolarBear.Plugin.IntroSkipper;
/// <summary>
/// Analyze all television episodes for introduction sequences.
/// </summary>
public class DetectIntrosTask : IScheduledTask
{
private readonly ILogger<DetectIntrosTask> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly ILibraryManager _libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="DetectIntrosTask"/> class.
/// </summary>
/// <param name="loggerFactory">Logger factory.</param>
/// <param name="libraryManager">Library manager.</param>
/// <param name="logger">Logger.</param>
public DetectIntrosTask(
ILogger<DetectIntrosTask> logger,
ILoggerFactory loggerFactory,
ILibraryManager libraryManager)
{
_logger = logger;
_loggerFactory = loggerFactory;
_libraryManager = libraryManager;
}
/// <summary>
/// Gets the task name.
/// </summary>
public string Name => "Detect Introductions";
/// <summary>
/// Gets the task category.
/// </summary>
public string Category => "Intro Skipper";
/// <summary>
/// Gets the task description.
/// </summary>
public string Description => "Analyzes the audio of all television episodes to find introduction sequences.";
/// <summary>
/// Gets the task key.
/// </summary>
public string Key => "CPBIntroSkipperDetectIntroductions";
/// <summary>
/// Analyze all episodes in the queue. Only one instance of this task should be run at a time.
/// </summary>
/// <param name="progress">Task progress.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Task.</returns>
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
if (_libraryManager is null)
{
throw new InvalidOperationException("Library manager was null");
}
// abort if analyzer is already running
if (Plugin.Instance!.AnalyzerTaskIsRunning)
{
return Task.CompletedTask;
}
else
{
Plugin.Instance!.AnalyzerTaskIsRunning = true;
}
var baseIntroAnalyzer = new BaseItemAnalyzerTask(
AnalysisMode.Introduction,
_loggerFactory.CreateLogger<DetectIntrosTask>(),
_loggerFactory,
_libraryManager);
baseIntroAnalyzer.AnalyzeItems(progress, cancellationToken);
Plugin.Instance!.AnalyzerTaskIsRunning = false;
return Task.CompletedTask;
}
/// <summary>
/// Get task triggers.
/// </summary>
/// <returns>Task triggers.</returns>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
return Array.Empty<TaskTriggerInfo>();
}
}