Skip to content

Commit

Permalink
Add chaining and logs to chapter analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
ConfusedPolarBear committed Nov 25, 2022
1 parent bfb821f commit 7439720
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void TestEndCreditsExpression(string chapterName)
config.ChapterAnalyzerIntroductionPattern :
config.ChapterAnalyzerEndCreditsPattern;

return analyzer.FindMatchingChapter(Guid.Empty, 2000, chapters, expression, mode);
return analyzer.FindMatchingChapter(new() { Duration = 2000 }, chapters, expression, mode);
}

private Collection<ChapterInfo> CreateChapters(string name, AnalysisMode mode)
Expand Down
44 changes: 29 additions & 15 deletions ConfusedPolarBear.Plugin.IntroSkipper/Analyzers/ChapterAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace ConfusedPolarBear.Plugin.IntroSkipper;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -30,7 +31,9 @@ public ReadOnlyCollection<QueuedEpisode> AnalyzeMediaFiles(
AnalysisMode mode,
CancellationToken cancellationToken)
{
var unsuccessful = new List<QueuedEpisode>();
var skippableRanges = new Dictionary<Guid, Intro>();

var expression = mode == AnalysisMode.Introduction ?
Plugin.Instance!.Configuration.ChapterAnalyzerIntroductionPattern :
Plugin.Instance!.Configuration.ChapterAnalyzerEndCreditsPattern;
Expand All @@ -43,14 +46,14 @@ public ReadOnlyCollection<QueuedEpisode> AnalyzeMediaFiles(
}

var skipRange = FindMatchingChapter(
episode.EpisodeId,
episode.Duration,
episode,
new(Plugin.Instance!.GetChapters(episode.EpisodeId)),
expression,
mode);

if (skipRange is null)
{
unsuccessful.Add(episode);
continue;
}

Expand All @@ -59,29 +62,28 @@ public ReadOnlyCollection<QueuedEpisode> AnalyzeMediaFiles(

Plugin.Instance!.UpdateTimestamps(skippableRanges, mode);

return analysisQueue;
return unsuccessful.AsReadOnly();
}

/// <summary>
/// Searches a list of chapter names for one that matches the provided regular expression.
/// Only public to allow for unit testing.
/// </summary>
/// <param name="id">Item id.</param>
/// <param name="duration">Duration of media file in seconds.</param>
/// <param name="episode">Episode.</param>
/// <param name="chapters">Media item chapters.</param>
/// <param name="expression">Regular expression pattern.</param>
/// <param name="mode">Analysis mode.</param>
/// <returns>Intro object containing skippable time range, or null if no chapter matched.</returns>
public Intro? FindMatchingChapter(
Guid id,
int duration,
QueuedEpisode episode,
Collection<ChapterInfo> chapters,
string expression,
AnalysisMode mode)
{
Intro? matchingChapter = null;

var config = Plugin.Instance?.Configuration ?? new Configuration.PluginConfiguration();

var minDuration = config.MinimumIntroDuration;
int maxDuration = mode == AnalysisMode.Introduction ?
config.MaximumIntroDuration :
Expand All @@ -91,28 +93,38 @@ public ReadOnlyCollection<QueuedEpisode> AnalyzeMediaFiles(
{
// Since the ending credits chapter may be the last chapter in the file, append a virtual
// chapter at the very end of the file.
chapters.Add(new ChapterInfo()
chapters.Add(new()
{
StartPositionTicks = TimeSpan.FromSeconds(duration).Ticks
StartPositionTicks = TimeSpan.FromSeconds(episode.Duration).Ticks
});
}

// Check all chapters
for (int i = 0; i < chapters.Count - 1; i++)
{
// Calculate chapter position and duration
var current = chapters[i];
var next = chapters[i + 1];

if (string.IsNullOrWhiteSpace(current.Name))
{
continue;
}

var currentRange = new TimeRange(
TimeSpan.FromTicks(current.StartPositionTicks).TotalSeconds,
TimeSpan.FromTicks(next.StartPositionTicks).TotalSeconds);

// Skip chapters with that don't have a name or are too short/long
if (string.IsNullOrEmpty(current.Name) ||
currentRange.Duration < minDuration ||
currentRange.Duration > maxDuration)
var baseMessage = string.Format(
CultureInfo.InvariantCulture,
"{0}: Chapter \"{1}\" ({2} - {3})",
episode.Path,
current.Name,
currentRange.Start,
currentRange.End);

if (currentRange.Duration < minDuration || currentRange.Duration > maxDuration)
{
_logger.LogTrace("{Base}: ignoring (invalid duration)", baseMessage);
continue;
}

Expand All @@ -126,10 +138,12 @@ public ReadOnlyCollection<QueuedEpisode> AnalyzeMediaFiles(

if (!match)
{
_logger.LogTrace("{Base}: ignoring (does not match regular expression)", baseMessage);
continue;
}

matchingChapter = new Intro(id, currentRange);
matchingChapter = new(episode.EpisodeId, currentRange);
_logger.LogTrace("{Base}: okay", baseMessage);
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ private int AnalyzeSeason(

// Chapter analyzer
var chapter = new ChapterAnalyzer(_loggerFactory.CreateLogger<ChapterAnalyzer>());
chapter.AnalyzeMediaFiles(episodes, AnalysisMode.Introduction, cancellationToken);
episodes = chapter.AnalyzeMediaFiles(episodes, AnalysisMode.Introduction, cancellationToken);

// Analyze the season with Chromaprint
var chromaprint = new ChromaprintAnalyzer(_loggerFactory.CreateLogger<ChromaprintAnalyzer>());
Expand Down

0 comments on commit 7439720

Please sign in to comment.