Merge pull request #56 from RepoDevil/master
Add parameters for ffmpeg options
This commit is contained in:
commit
77f43ed96e
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@ BenchmarkDotNet.Artifacts/
|
|||||||
|
|
||||||
# Ignore pre compiled web interface
|
# Ignore pre compiled web interface
|
||||||
docker/dist
|
docker/dist
|
||||||
|
|
||||||
|
# Visual Studio
|
||||||
|
.vs/
|
||||||
|
UpgradeLog*.htm
|
||||||
|
@ -7,8 +7,8 @@ using System.Globalization;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Chapter name analyzer.
|
/// Chapter name analyzer.
|
||||||
|
@ -275,10 +275,10 @@ public class ChromaprintAnalyzer : IMediaFileAnalyzer
|
|||||||
{
|
{
|
||||||
var modifiedPoint = (uint)(originalPoint + i);
|
var modifiedPoint = (uint)(originalPoint + i);
|
||||||
|
|
||||||
if (rhsIndex.ContainsKey(modifiedPoint))
|
if (rhsIndex.TryGetValue(modifiedPoint, out var value))
|
||||||
{
|
{
|
||||||
var lhsFirst = (int)lhsIndex[originalPoint];
|
var lhsFirst = (int)lhsIndex[originalPoint];
|
||||||
var rhsFirst = (int)rhsIndex[modifiedPoint];
|
var rhsFirst = (int)value;
|
||||||
indexShifts.Add(rhsFirst - lhsFirst);
|
indexShifts.Add(rhsFirst - lhsFirst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
|
|
||||||
namespace ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
namespace ConfusedPolarBear.Plugin.IntroSkipper.Configuration;
|
||||||
@ -181,4 +182,14 @@ public class PluginConfiguration : BasePluginConfiguration
|
|||||||
/// Gets or sets the notification text sent after automatically skipping an introduction.
|
/// Gets or sets the notification text sent after automatically skipping an introduction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AutoSkipNotificationText { get; set; } = "Intro skipped";
|
public string AutoSkipNotificationText { get; set; } = "Intro skipped";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the number of threads for an ffmpeg process.
|
||||||
|
/// </summary>
|
||||||
|
public int ProcessThreads { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the relative priority for an ffmpeg process.
|
||||||
|
/// </summary>
|
||||||
|
public ProcessPriorityClass ProcessPriority { get; set; } = ProcessPriorityClass.BelowNormal;
|
||||||
}
|
}
|
||||||
|
@ -59,77 +59,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label class="emby-checkbox-label">
|
|
||||||
<input id="CacheFingerprints" type="checkbox" is="emby-checkbox" />
|
|
||||||
<span>Cache episode fingerprints</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="fieldDescription">
|
|
||||||
If checked, episode fingerprints will be cached to the filesystem
|
|
||||||
<br />
|
|
||||||
<strong>WARNING: Disabling cache may result in lengthy detection</strong>
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<details id="edl">
|
|
||||||
<summary>EDL file generation</summary>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
<div class="selectContainer">
|
|
||||||
<label class="selectLabel" for="EdlAction">EDL Action</label>
|
|
||||||
<select is="emby-select" id="EdlAction" class="emby-select-withcolor emby-select">
|
|
||||||
<option value="None">
|
|
||||||
None (do not create or modify EDL files)
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="CommercialBreak">
|
|
||||||
Commercial Break (recommended, skips past the intro once)
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="Cut">
|
|
||||||
Cut (player will remove the intro from the video)
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="Intro">
|
|
||||||
Intro (show a skip button, *experimental*)
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="Mute">
|
|
||||||
Mute (audio will be muted)
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="SceneMarker">
|
|
||||||
Scene Marker (create a chapter marker)
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="fieldDescription">
|
|
||||||
If set to a value other than None, specifies which action to write to
|
|
||||||
<a href="https://kodi.wiki/view/Edit_decision_list">MPlayer compatible EDL files</a>
|
|
||||||
alongside your episode files. <br />
|
|
||||||
|
|
||||||
If this value is changed after EDL files are generated, you must check the
|
|
||||||
"Regenerate EDL files" checkbox below.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label class="emby-checkbox-label">
|
|
||||||
<input id="RegenerateEdlFiles" type="checkbox" is="emby-checkbox" />
|
|
||||||
<span>Regenerate EDL files during next scan</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="fieldDescription">
|
|
||||||
If checked, the plugin will <strong>overwrite all EDL files</strong> associated with
|
|
||||||
your episodes with the currently discovered introduction timestamps and EDL action.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details id="intro_reqs">
|
<details id="intro_reqs">
|
||||||
<summary>Modify introduction requirements</summary>
|
<summary>Modify Intro Parameters</summary>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
@ -193,8 +124,63 @@
|
|||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details id="edl">
|
||||||
|
<summary>EDL File Generation</summary>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div class="selectContainer">
|
||||||
|
<label class="selectLabel" for="EdlAction">EDL Action</label>
|
||||||
|
<select is="emby-select" id="EdlAction" class="emby-select-withcolor emby-select">
|
||||||
|
<option value="None">
|
||||||
|
None (do not create or modify EDL files)
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="CommercialBreak">
|
||||||
|
Commercial Break (recommended, skips past the intro once)
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="Cut">
|
||||||
|
Cut (player will remove the intro from the video)
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="Intro">
|
||||||
|
Intro (show a skip button, *experimental*)
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="Mute">
|
||||||
|
Mute (audio will be muted)
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="SceneMarker">
|
||||||
|
Scene Marker (create a chapter marker)
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div class="fieldDescription">
|
||||||
|
If set to a value other than None, specifies which action to write to
|
||||||
|
<a href="https://kodi.wiki/view/Edit_decision_list">MPlayer compatible EDL files</a>
|
||||||
|
alongside your episode files. <br />
|
||||||
|
|
||||||
|
If this value is changed after EDL files are generated, you must check the
|
||||||
|
"Regenerate EDL files" checkbox below.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label class="emby-checkbox-label">
|
||||||
|
<input id="RegenerateEdlFiles" type="checkbox" is="emby-checkbox" />
|
||||||
|
<span>Regenerate EDL files during next scan</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="fieldDescription">
|
||||||
|
If checked, the plugin will <strong>overwrite all EDL files</strong> associated with
|
||||||
|
your episodes with the currently discovered introduction timestamps and EDL action.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
<details id="silence">
|
<details id="silence">
|
||||||
<summary>Silence detection options</summary>
|
<summary>Silence Detection Options</summary>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
@ -219,6 +205,73 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details id="detection">
|
||||||
|
<summary>Process Configuration</summary>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label class="emby-checkbox-label">
|
||||||
|
<input id="CacheFingerprints" type="checkbox" is="emby-checkbox" />
|
||||||
|
<span>Cache episode fingerprints</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="fieldDescription">
|
||||||
|
If checked, episode fingerprints will be saved on the filesystem to improve analysis speed.
|
||||||
|
<br />
|
||||||
|
<strong>WARNING: May result in lengthy detection! Not recommended for large libraries!</strong>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="selectContainer">
|
||||||
|
<label class="selectLabel" for="ProcessPriority">ffmpeg Priority</label>
|
||||||
|
<select is="emby-select" id="ProcessPriority" class="emby-select-withcolor emby-select">
|
||||||
|
<option value="Idle">
|
||||||
|
Idle
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="BelowNormal">
|
||||||
|
Below Normal
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="Normal">
|
||||||
|
Normal
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="AboveNormal">
|
||||||
|
Above Normal
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="High">
|
||||||
|
High
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="RealTime">
|
||||||
|
Highest
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div class="fieldDescription">
|
||||||
|
Sets the relative priority of the analysis ffmpeg process to other parallel operations
|
||||||
|
(ie. transcoding, chapter detection, etc).
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<label class="inputLabel inputLabelUnfocused" for="ProcessThreads">
|
||||||
|
ffmpeg Threads
|
||||||
|
</label>
|
||||||
|
<input id="ProcessThreads" type="number" is="emby-input" min="0"
|
||||||
|
max="16" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
Number of simultaneous processes to use for ffmpeg operations.
|
||||||
|
<br />
|
||||||
|
This value is most often defined as 1 thread per CPU core,
|
||||||
|
but setting a value of 0 (default) will use the maximum threads available.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="verticalSection-extrabottompadding">
|
<fieldset class="verticalSection-extrabottompadding">
|
||||||
@ -268,7 +321,7 @@
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="fieldDescription">
|
<div class="fieldDescription">
|
||||||
If checked, skip button will appear through entire intro (offset and timeout are ignored).<br />
|
If checked, skip button will appear throughout entire intro (offset and timeout are ignored).<br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -388,12 +441,12 @@
|
|||||||
</button>
|
</button>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
</div>
|
||||||
|
|
||||||
<button id="btnEraseSeasonTimestamps" type="button">
|
<button id="btnEraseSeasonTimestamps" type="button" style="display:none;">
|
||||||
Erase all timestamps for this season
|
Erase all timestamps for this season
|
||||||
</button>
|
</button>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="btnEraseIntroTimestamps">
|
<button id="btnEraseIntroTimestamps">
|
||||||
Erase all introduction timestamps (globally)
|
Erase all introduction timestamps (globally)
|
||||||
@ -491,6 +544,8 @@
|
|||||||
"MinimumIntroDuration",
|
"MinimumIntroDuration",
|
||||||
"MaximumIntroDuration",
|
"MaximumIntroDuration",
|
||||||
"EdlAction",
|
"EdlAction",
|
||||||
|
"ProcessPriority",
|
||||||
|
"ProcessThreads",
|
||||||
// playback
|
// playback
|
||||||
"ShowPromptAdjustment",
|
"ShowPromptAdjustment",
|
||||||
"HidePromptAdjustment",
|
"HidePromptAdjustment",
|
||||||
@ -506,8 +561,8 @@
|
|||||||
|
|
||||||
var booleanConfigurationFields = [
|
var booleanConfigurationFields = [
|
||||||
"AnalyzeSeasonZero",
|
"AnalyzeSeasonZero",
|
||||||
"CacheFingerprints",
|
|
||||||
"RegenerateEdlFiles",
|
"RegenerateEdlFiles",
|
||||||
|
"CacheFingerprints",
|
||||||
"AutoSkip",
|
"AutoSkip",
|
||||||
"SkipFirstEpisode",
|
"SkipFirstEpisode",
|
||||||
"PersistSkipButton",
|
"PersistSkipButton",
|
||||||
@ -618,6 +673,7 @@
|
|||||||
// show changed, populate seasons
|
// show changed, populate seasons
|
||||||
async function showChanged() {
|
async function showChanged() {
|
||||||
clearSelect(selectSeason);
|
clearSelect(selectSeason);
|
||||||
|
btnSeasonEraseTimestamps.style.display = "none";
|
||||||
|
|
||||||
// add all seasons from this show to the season select
|
// add all seasons from this show to the season select
|
||||||
for (var season of shows[selectShow.value]) {
|
for (var season of shows[selectShow.value]) {
|
||||||
@ -634,6 +690,7 @@
|
|||||||
|
|
||||||
clearSelect(selectEpisode1);
|
clearSelect(selectEpisode1);
|
||||||
clearSelect(selectEpisode2);
|
clearSelect(selectEpisode2);
|
||||||
|
btnSeasonEraseTimestamps.style.display = "block";
|
||||||
|
|
||||||
let i = 1;
|
let i = 1;
|
||||||
for (let episode of episodes) {
|
for (let episode of episodes) {
|
||||||
@ -714,7 +771,7 @@
|
|||||||
|
|
||||||
// make an authenticated GET to the server and parse the response as JSON
|
// make an authenticated GET to the server and parse the response as JSON
|
||||||
async function getJson(url) {
|
async function getJson(url) {
|
||||||
return await fetchWithAuth(url, "GET").then(r => { return r.json(); });
|
return await fetchWithAuth(url, "GET").then(r => { return r.json(); }).catch(err => { console.debug(err) });
|
||||||
}
|
}
|
||||||
|
|
||||||
// make an authenticated fetch to the server
|
// make an authenticated fetch to the server
|
||||||
|
@ -1,25 +1,22 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>ConfusedPolarBear.Plugin.IntroSkipper</RootNamespace>
|
<RootNamespace>ConfusedPolarBear.Plugin.IntroSkipper</RootNamespace>
|
||||||
<AssemblyVersion>0.1.14.0</AssemblyVersion>
|
<AssemblyVersion>0.1.15.0</AssemblyVersion>
|
||||||
<FileVersion>0.1.14.0</FileVersion>
|
<FileVersion>0.1.15.0</FileVersion>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||||
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Jellyfin.Controller" Version="10.8.*" />
|
<PackageReference Include="Jellyfin.Controller" Version="10.8.*" />
|
||||||
<PackageReference Include="Jellyfin.Model" Version="10.8.*" />
|
<PackageReference Include="Jellyfin.Model" Version="10.8.*" />
|
||||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
|
|
||||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Configuration\configPage.html" />
|
<None Remove="Configuration\configPage.html" />
|
||||||
<EmbeddedResource Include="Configuration\configPage.html" />
|
<EmbeddedResource Include="Configuration\configPage.html" />
|
||||||
@ -27,5 +24,4 @@
|
|||||||
<EmbeddedResource Include="Configuration\inject.js" />
|
<EmbeddedResource Include="Configuration\inject.js" />
|
||||||
<EmbeddedResource Include="Configuration\version.txt" />
|
<EmbeddedResource Include="Configuration\version.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -400,8 +400,9 @@ public static class FFmpegWrapper
|
|||||||
// for each file that is fingerprinted.
|
// for each file that is fingerprinted.
|
||||||
var prependArgument = string.Format(
|
var prependArgument = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"-hide_banner -loglevel {0} ",
|
"-hide_banner -loglevel {0} -threads {1} ",
|
||||||
logLevel);
|
logLevel,
|
||||||
|
Plugin.Instance?.Configuration.ProcessThreads ?? 0);
|
||||||
|
|
||||||
var info = new ProcessStartInfo(ffmpegPath, args.Insert(0, prependArgument))
|
var info = new ProcessStartInfo(ffmpegPath, args.Insert(0, prependArgument))
|
||||||
{
|
{
|
||||||
@ -425,6 +426,17 @@ public static class FFmpegWrapper
|
|||||||
|
|
||||||
ffmpeg.Start();
|
ffmpeg.Start();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ffmpeg.PriorityClass = Plugin.Instance?.Configuration.ProcessPriority ?? ProcessPriorityClass.BelowNormal;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger?.LogDebug(
|
||||||
|
"ffmpeg priority could not be modified. {Message}",
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = new MemoryStream())
|
||||||
{
|
{
|
||||||
var buf = new byte[4096];
|
var buf = new byte[4096];
|
||||||
|
10
ConfusedPolarBear.Plugin.IntroSkipper/GlobalSuppressions.cs
Normal file
10
ConfusedPolarBear.Plugin.IntroSkipper/GlobalSuppressions.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "Legacy TODO", Scope = "type", Target = "~T:ConfusedPolarBear.Plugin.IntroSkipper.WarningManager")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Legacy TODO", Scope = "type", Target = "~T:ConfusedPolarBear.Plugin.IntroSkipper.IntroWithMetadata")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Legacy TODO", Scope = "type", Target = "~T:ConfusedPolarBear.Plugin.IntroSkipper.TimeRangeHelpers")]
|
@ -331,7 +331,7 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|||||||
private void InjectSkipButton(string indexPath)
|
private void InjectSkipButton(string indexPath)
|
||||||
{
|
{
|
||||||
// Parts of this code are based off of JellyScrub's script injection code.
|
// Parts of this code are based off of JellyScrub's script injection code.
|
||||||
// https://github.com/nicknsy/jellyscrub/blob/4ce806f602988a662cfe3cdbaac35ee8046b7ec4/Nick.Plugin.Jellyscrub/JellyscrubPlugin.cs
|
// https://github.com/nicknsy/jellyscrub/blob/main/Nick.Plugin.Jellyscrub/JellyscrubPlugin.cs#L38
|
||||||
|
|
||||||
_logger.LogDebug("Reading index.html from {Path}", indexPath);
|
_logger.LogDebug("Reading index.html from {Path}", indexPath);
|
||||||
var contents = File.ReadAllText(indexPath);
|
var contents = File.ReadAllText(indexPath);
|
||||||
|
@ -43,13 +43,6 @@ public class QueueManager
|
|||||||
/// <returns>Queued media items.</returns>
|
/// <returns>Queued media items.</returns>
|
||||||
public ReadOnlyDictionary<Guid, List<QueuedEpisode>> GetMediaItems()
|
public ReadOnlyDictionary<Guid, List<QueuedEpisode>> GetMediaItems()
|
||||||
{
|
{
|
||||||
// Assert that ffmpeg with chromaprint is installed
|
|
||||||
if (!FFmpegWrapper.CheckFFmpegVersion())
|
|
||||||
{
|
|
||||||
throw new FingerprintException(
|
|
||||||
"ffmpeg with chromaprint is not installed on this system - episodes will not be analyzed. If Jellyfin is running natively, install jellyfin-ffmpeg5. If Jellyfin is running in a container, upgrade it to the latest version of 10.8.0.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin.Instance!.TotalQueued = 0;
|
Plugin.Instance!.TotalQueued = 0;
|
||||||
|
|
||||||
LoadAnalysisSettings();
|
LoadAnalysisSettings();
|
||||||
|
@ -53,6 +53,13 @@ public class BaseItemAnalyzerTask
|
|||||||
IProgress<double> progress,
|
IProgress<double> progress,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// Assert that ffmpeg with chromaprint is installed
|
||||||
|
if (!FFmpegWrapper.CheckFFmpegVersion())
|
||||||
|
{
|
||||||
|
throw new FingerprintException(
|
||||||
|
"ffmpeg with chromaprint is not installed on this system - episodes will not be analyzed. If Jellyfin is running natively, install jellyfin-ffmpeg5. If Jellyfin is running in a container, upgrade it to the latest version of 10.8.0.");
|
||||||
|
}
|
||||||
|
|
||||||
var queueManager = new QueueManager(
|
var queueManager = new QueueManager(
|
||||||
_loggerFactory.CreateLogger<QueueManager>(),
|
_loggerFactory.CreateLogger<QueueManager>(),
|
||||||
_libraryManager);
|
_libraryManager);
|
||||||
|
@ -17,14 +17,14 @@ This fork doesn't ship the custom web interface on your server. So the plugin ne
|
|||||||
* Debian Linux based native installs: provided by the `jellyfin-ffmpeg5` package
|
* Debian Linux based native installs: provided by the `jellyfin-ffmpeg5` package
|
||||||
* MacOS native installs: build ffmpeg with chromaprint support ([instructions](#installation-instructions-for-macos))
|
* MacOS native installs: build ffmpeg with chromaprint support ([instructions](#installation-instructions-for-macos))
|
||||||
|
|
||||||
## Introduction requirements
|
## Introduction parameters
|
||||||
|
|
||||||
Show introductions will only be detected if they are:
|
Show introductions will be detected if they are:
|
||||||
|
|
||||||
* Located within the first 25% of an episode, or the first 10 minutes, whichever is smaller
|
* Located within the first 25% of an episode or the first 10 minutes, whichever is smaller
|
||||||
* Between 15 seconds and 2 minutes long
|
* Between 15 seconds and 2 minutes long
|
||||||
|
|
||||||
Ending credits will only be detected if they are shorter than 4 minutes.
|
Ending credits will be detected if they are shorter than 4 minutes.
|
||||||
|
|
||||||
All of these requirements can be customized as needed.
|
All of these requirements can be customized as needed.
|
||||||
|
|
||||||
|
@ -4,10 +4,18 @@
|
|||||||
"name": "Intro Skipper",
|
"name": "Intro Skipper",
|
||||||
"overview": "Automatically detect and skip intros in television episodes",
|
"overview": "Automatically detect and skip intros in television episodes",
|
||||||
"description": "Analyzes the audio of television episodes and detects introduction sequences.",
|
"description": "Analyzes the audio of television episodes and detects introduction sequences.",
|
||||||
"owner": "ConfusedPolarBear",
|
"owner": "jumoog, AbandonedCart (forked from ConfusedPolarBear)",
|
||||||
"category": "General",
|
"category": "General",
|
||||||
"imageUrl": "https://raw.githubusercontent.com/jumoog/intro-skipper/master/images/logo.png",
|
"imageUrl": "https://raw.githubusercontent.com/jumoog/intro-skipper/master/images/logo.png",
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"version": "0.1.15.0",
|
||||||
|
"changelog": "- See the full changelog at [GitHub](https://github.com/jumoog/intro-skipper/blob/master/CHANGELOG.md)\n",
|
||||||
|
"targetAbi": "10.8.4.0",
|
||||||
|
"sourceUrl": "https://github.com/jumoog/intro-skipper/releases/download/v0.1.15/intro-skipper-v0.1.15.zip",
|
||||||
|
"checksum": "cf05593afbb2be39b8de31dcb7fd8a50",
|
||||||
|
"timestamp": "2024-03-03T09:08:10Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.1.14.0",
|
"version": "0.1.14.0",
|
||||||
"changelog": "- See the full changelog at [GitHub](https://github.com/jumoog/intro-skipper/blob/master/CHANGELOG.md)\n",
|
"changelog": "- See the full changelog at [GitHub](https://github.com/jumoog/intro-skipper/blob/master/CHANGELOG.md)\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user