Server side works
This commit is contained in:
parent
a1862d0e2f
commit
98f73c3dba
@ -1,23 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
|
|
||||||
namespace ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
namespace ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The configuration options.
|
|
||||||
/// </summary>
|
|
||||||
public enum SomeOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Option one.
|
|
||||||
/// </summary>
|
|
||||||
OneOption,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Second option.
|
|
||||||
/// </summary>
|
|
||||||
AnotherOption
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plugin configuration.
|
/// Plugin configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,30 +16,38 @@ public class PluginConfiguration : BasePluginConfiguration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public PluginConfiguration()
|
public PluginConfiguration()
|
||||||
{
|
{
|
||||||
// set default options here
|
AnalysisResults = new Collection<Intro>();
|
||||||
Options = SomeOptions.AnotherOption;
|
|
||||||
TrueFalseSetting = true;
|
|
||||||
AnInteger = 2;
|
|
||||||
AString = "string";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether some true or false setting is enabled..
|
/// Save timestamps to disk.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TrueFalseSetting { get; set; }
|
public void SaveTimestamps()
|
||||||
|
{
|
||||||
|
AnalysisResults.Clear();
|
||||||
|
|
||||||
|
foreach (var intro in Plugin.Instance!.Intros)
|
||||||
|
{
|
||||||
|
AnalysisResults.Add(intro.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.Instance!.SaveConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets an integer setting.
|
/// Restore previous analysis results from disk.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int AnInteger { get; set; }
|
public void RestoreTimestamps()
|
||||||
|
{
|
||||||
|
// Since dictionaries can't be easily serialized, analysis results are stored on disk as a list.
|
||||||
|
foreach (var intro in AnalysisResults)
|
||||||
|
{
|
||||||
|
Plugin.Instance!.Intros[intro.EpisodeId] = intro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a string setting.
|
/// Previous analysis results.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AString { get; set; }
|
public Collection<Intro> AnalysisResults { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets an enum option.
|
|
||||||
/// </summary>
|
|
||||||
public SomeOptions Options { get; set; }
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Text.Json;
|
|
||||||
using Jellyfin.Data.Entities;
|
|
||||||
using Jellyfin.Extensions.Json;
|
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace ConfusedPolarBear.Plugin.IntroSkipper.Controllers;
|
namespace ConfusedPolarBear.Plugin.IntroSkipper.Controllers;
|
||||||
|
|
||||||
@ -33,18 +23,18 @@ public class SkipIntroController : ControllerBase
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the timestamps of the introduction in a television episode.
|
/// Returns the timestamps of the introduction in a television episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="episodeId">ID of the episode. Required.</param>
|
/// <param name="id">ID of the episode. Required.</param>
|
||||||
/// <response code="200">Episode contains an intro.</response>
|
/// <response code="200">Episode contains an intro.</response>
|
||||||
/// <response code="404">Failed to find an intro in the provided episode.</response>
|
/// <response code="404">Failed to find an intro in the provided episode.</response>
|
||||||
[HttpGet("Episode/{id}/IntroTimestamps")]
|
[HttpGet("Episode/{id}/IntroTimestamps")]
|
||||||
public ActionResult<Intro> GetIntroTimestamps([FromRoute] Guid episodeId)
|
public ActionResult<Intro> GetIntroTimestamps([FromRoute] Guid id)
|
||||||
{
|
{
|
||||||
if (!Plugin.Instance!.Intros.ContainsKey(episodeId))
|
if (!Plugin.Instance!.Intros.ContainsKey(id))
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var intro = Plugin.Instance!.Intros[episodeId];
|
var intro = Plugin.Instance!.Intros[id];
|
||||||
|
|
||||||
// Check that the episode was analyzed successfully.
|
// Check that the episode was analyzed successfully.
|
||||||
if (!intro.Valid)
|
if (!intro.Valid)
|
||||||
|
@ -6,8 +6,12 @@ namespace ConfusedPolarBear.Plugin.IntroSkipper;
|
|||||||
/// Result of fingerprinting and analyzing two episodes in a season.
|
/// Result of fingerprinting and analyzing two episodes in a season.
|
||||||
/// All times are measured in seconds relative to the beginning of the media file.
|
/// All times are measured in seconds relative to the beginning of the media file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
|
||||||
public class Intro {
|
public class Intro {
|
||||||
|
/// <summary>
|
||||||
|
/// Episode ID.
|
||||||
|
/// </summary>
|
||||||
|
public Guid EpisodeId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If this introduction is valid or not. Invalid results should not be returned through the API.
|
/// If this introduction is valid or not. Invalid results should not be returned through the API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
using ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
||||||
@ -11,10 +10,25 @@ using MediaBrowser.Model.Serialization;
|
|||||||
namespace ConfusedPolarBear.Plugin.IntroSkipper;
|
namespace ConfusedPolarBear.Plugin.IntroSkipper;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main plugin.
|
/// Intro skipper plugin. Uses audio analysis to find common sequences of audio shared between episodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Plugin"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
||||||
|
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
||||||
|
public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||||
|
: base(applicationPaths, xmlSerializer)
|
||||||
|
{
|
||||||
|
Intros = new Dictionary<Guid, Intro>();
|
||||||
|
AnalysisQueue = new Dictionary<Guid, List<QueuedEpisode>>();
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
Configuration.RestoreTimestamps();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Results of fingerprinting all episodes.
|
/// Results of fingerprinting all episodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -30,29 +44,13 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int TotalQueued { get; set; }
|
public int TotalQueued { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="Plugin"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
|
||||||
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
|
||||||
public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
|
||||||
: base(applicationPaths, xmlSerializer)
|
|
||||||
{
|
|
||||||
Intros = new Dictionary<Guid, Intro>();
|
|
||||||
AnalysisQueue = new Dictionary<Guid, List<QueuedEpisode>>();
|
|
||||||
|
|
||||||
Instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string Name => "Intro Skipper";
|
public override string Name => "Intro Skipper";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Guid Id => Guid.Parse("c83d86bb-a1e0-4c35-a113-e2101cf4ee6b");
|
public override Guid Id => Guid.Parse("c83d86bb-a1e0-4c35-a113-e2101cf4ee6b");
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Gets the current plugin instance.
|
|
||||||
/// </summary>
|
|
||||||
public static Plugin? Instance { get; private set; }
|
public static Plugin? Instance { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -119,7 +119,7 @@ public class FingerprinterTask : IScheduledTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: after every season completes, serialize fingerprints to disk somewhere
|
Plugin.Instance!.Configuration.SaveTimestamps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@ -248,10 +248,11 @@ public class FingerprinterTask : IScheduledTask {
|
|||||||
// and that it disappears 10 seconds after the intro begins.
|
// and that it disappears 10 seconds after the intro begins.
|
||||||
Plugin.Instance!.Intros[episode] = new Intro()
|
Plugin.Instance!.Intros[episode] = new Intro()
|
||||||
{
|
{
|
||||||
|
EpisodeId = episode,
|
||||||
Valid = (introStart > 0) && (introEnd > 0),
|
Valid = (introStart > 0) && (introEnd > 0),
|
||||||
IntroStart = introStart,
|
IntroStart = introStart,
|
||||||
IntroEnd = introEnd,
|
IntroEnd = introEnd,
|
||||||
ShowSkipPromptAt = Math.Min(0, introStart - 5),
|
ShowSkipPromptAt = Math.Max(0, introStart - 5),
|
||||||
HideSkipPromptAt = introStart + 10
|
HideSkipPromptAt = introStart + 10
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user