feat: add configurable multi-threaded parallel scanning for library tasks
This commit is contained in:
@@ -12,5 +12,8 @@ namespace JellyfinPlugin.Configuration
|
||||
|
||||
// Tryb odtwarzania: "Server" (FFmpeg wrapper), "Client" (CSS injection w Web UI), "Auto" (Automatyczny: CSS dla Web, FFmpeg dla aplikacji natywnych)
|
||||
public string PlaybackMode { get; set; } = "Auto";
|
||||
|
||||
// Maksymalna liczba równoległych wątków skanowania czarnych pasów (1 - 16, domyślnie 4)
|
||||
public int MaxParallelScans { get; set; } = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
<div class="fieldDescription">Choose how the plugin should remove black bars. Auto mode uses lightweight CSS clipping for Web browser DirectPlay, and falls back to FFmpeg transcoding for native apps or unsupported video formats.</div>
|
||||
</div>
|
||||
|
||||
<div class="inputContainer">
|
||||
<label class="inputLabel inputLabelUnfocused" for="txtMaxParallelScans">Max Parallel Scans (1 - 16):</label>
|
||||
<input type="number" step="1" min="1" max="16" id="txtMaxParallelScans" is="emby-input" required />
|
||||
<div class="fieldDescription">Number of files to analyze concurrently during library scheduled tasks. Default is 4. Higher values speed up library scans on multi-core CPUs.</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button is="emby-button" type="submit" class="raised button-submit block emby-button">
|
||||
<span>Save</span>
|
||||
@@ -56,6 +62,7 @@
|
||||
var mode = config.PlaybackMode || "Auto";
|
||||
if (mode === "Both") mode = "Auto";
|
||||
$('#selectPlaybackMode', page).val(mode);
|
||||
$('#txtMaxParallelScans', page).val(config.MaxParallelScans || 4);
|
||||
Dashboard.hideLoadingMsg();
|
||||
});
|
||||
});
|
||||
@@ -69,6 +76,7 @@
|
||||
config.IsEnabled = $('#chkEnablePlugin', form).prop('checked');
|
||||
config.CropDetectLimit = parseFloat($('#txtCropLimit', form).val());
|
||||
config.PlaybackMode = $('#selectPlaybackMode', form).val();
|
||||
config.MaxParallelScans = parseInt($('#txtMaxParallelScans', form).val(), 10) || 4;
|
||||
|
||||
ApiClient.updatePluginConfiguration(BlackBarRemoverConfig.pluginUniqueId, config).then(function (result) {
|
||||
Dashboard.processPluginConfigurationUpdateResult(result);
|
||||
|
||||
@@ -42,15 +42,21 @@ namespace JellyfinPlugin.Tasks
|
||||
.ToList();
|
||||
|
||||
int total = items.Count;
|
||||
if (total == 0) return;
|
||||
|
||||
int processed = 0;
|
||||
int maxParallel = Math.Clamp(config.MaxParallelScans, 1, 16);
|
||||
|
||||
foreach (var item in items)
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Wymuszamy skanowanie, więc nie sprawdzamy czy ma już BlackBarCrop
|
||||
MaxDegreeOfParallelism = maxParallel,
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
_logger.LogInformation("Starting Force Rescan of {Total} items with {MaxParallel} parallel workers.", total, maxParallel);
|
||||
|
||||
await Parallel.ForEachAsync(items, parallelOptions, async (item, ct) =>
|
||||
{
|
||||
var path = item.Path;
|
||||
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||
{
|
||||
@@ -65,7 +71,7 @@ namespace JellyfinPlugin.Tasks
|
||||
item.ProviderIds = new Dictionary<string, string>();
|
||||
}
|
||||
item.ProviderIds["BlackBarCrop"] = cropData;
|
||||
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, cancellationToken);
|
||||
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, ct);
|
||||
_logger.LogInformation("Found black bars {Crop} in {Path}", cropData, path);
|
||||
}
|
||||
}
|
||||
@@ -75,9 +81,9 @@ namespace JellyfinPlugin.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
processed++;
|
||||
progress.Report((processed / (double)total) * 100);
|
||||
}
|
||||
int current = Interlocked.Increment(ref processed);
|
||||
progress.Report((current / (double)total) * 100);
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
|
||||
@@ -42,19 +42,28 @@ namespace JellyfinPlugin.Tasks
|
||||
.ToList();
|
||||
|
||||
int total = items.Count;
|
||||
if (total == 0) return;
|
||||
|
||||
int processed = 0;
|
||||
int maxParallel = Math.Clamp(config.MaxParallelScans, 1, 16);
|
||||
|
||||
foreach (var item in items)
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
MaxDegreeOfParallelism = maxParallel,
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
_logger.LogInformation("Starting Retroactive Scan of {Total} items with {MaxParallel} parallel workers.", total, maxParallel);
|
||||
|
||||
await Parallel.ForEachAsync(items, parallelOptions, async (item, ct) =>
|
||||
{
|
||||
if (item.ProviderIds != null &&
|
||||
item.ProviderIds.TryGetValue("BlackBarCrop", out string? existingCrop) &&
|
||||
!string.IsNullOrEmpty(existingCrop))
|
||||
{
|
||||
processed++;
|
||||
progress.Report((processed / (double)total) * 100);
|
||||
continue;
|
||||
int currentSkipped = Interlocked.Increment(ref processed);
|
||||
progress.Report((currentSkipped / (double)total) * 100);
|
||||
return;
|
||||
}
|
||||
|
||||
var path = item.Path;
|
||||
@@ -71,7 +80,7 @@ namespace JellyfinPlugin.Tasks
|
||||
item.ProviderIds = new Dictionary<string, string>();
|
||||
}
|
||||
item.ProviderIds["BlackBarCrop"] = cropData;
|
||||
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, cancellationToken);
|
||||
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, ct);
|
||||
_logger.LogInformation("Found black bars {Crop} in {Path}", cropData, path);
|
||||
}
|
||||
}
|
||||
@@ -81,9 +90,9 @@ namespace JellyfinPlugin.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
processed++;
|
||||
progress.Report((processed / (double)total) * 100);
|
||||
}
|
||||
int currentDone = Interlocked.Increment(ref processed);
|
||||
progress.Report((currentDone / (double)total) * 100);
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
|
||||
Reference in New Issue
Block a user