fix: resolve ffmpeg path dynamically, handle empty crop check, and strip quotes in wrapper
This commit is contained in:
@@ -25,6 +25,7 @@ namespace JellyfinPlugin.Api
|
|||||||
public ContentResult GetCropByPath([FromQuery] string path)
|
public ContentResult GetCropByPath([FromQuery] string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(path)) return Content(string.Empty, "text/plain");
|
if (string.IsNullOrEmpty(path)) return Content(string.Empty, "text/plain");
|
||||||
|
path = path.Trim('"').Trim('\'');
|
||||||
|
|
||||||
var mode = Plugin.Instance!.Configuration.PlaybackMode;
|
var mode = Plugin.Instance!.Configuration.PlaybackMode;
|
||||||
if (mode == "Client") return Content(string.Empty, "text/plain");
|
if (mode == "Client") return Content(string.Empty, "text/plain");
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ namespace JellyfinPlugin
|
|||||||
{
|
{
|
||||||
public static class CropHelper
|
public static class CropHelper
|
||||||
{
|
{
|
||||||
|
private static string GetFFmpegPath()
|
||||||
|
{
|
||||||
|
if (File.Exists("/usr/lib/jellyfin-ffmpeg/ffmpeg")) return "/usr/lib/jellyfin-ffmpeg/ffmpeg";
|
||||||
|
if (File.Exists("/usr/bin/ffmpeg")) return "/usr/bin/ffmpeg";
|
||||||
|
return "ffmpeg";
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<string> DetectCropAsync(string filePath, double limit)
|
public static async Task<string> DetectCropAsync(string filePath, double limit)
|
||||||
{
|
{
|
||||||
// FFmpeg w nowych wersjach przyjmuje limit w formie ułamka, np. 24/255 to ok 0.094
|
// FFmpeg w nowych wersjach przyjmuje limit w formie ułamka, np. 24/255 to ok 0.094
|
||||||
@@ -17,7 +24,7 @@ namespace JellyfinPlugin
|
|||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "ffmpeg",
|
FileName = GetFFmpegPath(),
|
||||||
// KLUCZOWE: reset=1, żeby oceniał każdą klatkę niezależnie!
|
// KLUCZOWE: reset=1, żeby oceniał każdą klatkę niezależnie!
|
||||||
Arguments = $"-skip_frame nokey -i \"{filePath}\" -vf \"cropdetect=limit={limitStr}:round=16:reset=1\" -f null -",
|
Arguments = $"-skip_frame nokey -i \"{filePath}\" -vf \"cropdetect=limit={limitStr}:round=16:reset=1\" -f null -",
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ namespace JellyfinPlugin
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (video.ProviderIds != null && video.ProviderIds.ContainsKey("BlackBarCrop"))
|
if (video.ProviderIds != null &&
|
||||||
|
video.ProviderIds.TryGetValue("BlackBarCrop", out string? existingCrop) &&
|
||||||
|
!string.IsNullOrEmpty(existingCrop))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ namespace JellyfinPlugin.Tasks
|
|||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
if (item.ProviderIds != null && item.ProviderIds.ContainsKey("BlackBarCrop"))
|
if (item.ProviderIds != null &&
|
||||||
|
item.ProviderIds.TryGetValue("BlackBarCrop", out string? existingCrop) &&
|
||||||
|
!string.IsNullOrEmpty(existingCrop))
|
||||||
{
|
{
|
||||||
processed++;
|
processed++;
|
||||||
progress.Report((processed / (double)total) * 100);
|
progress.Report((processed / (double)total) * 100);
|
||||||
@@ -62,18 +64,16 @@ namespace JellyfinPlugin.Tasks
|
|||||||
{
|
{
|
||||||
string cropData = await CropHelper.DetectCropAsync(path, config.CropDetectLimit);
|
string cropData = await CropHelper.DetectCropAsync(path, config.CropDetectLimit);
|
||||||
|
|
||||||
if (item.ProviderIds == null)
|
|
||||||
{
|
|
||||||
item.ProviderIds = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zawsze dodajemy flagę, nawet jak puste, żeby nie skanować drugi raz tego samego pliku
|
|
||||||
// (puste oznacza że nie ma czarnych pasów do ucięcia)
|
|
||||||
item.ProviderIds["BlackBarCrop"] = cropData ?? string.Empty;
|
|
||||||
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, cancellationToken);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(cropData))
|
if (!string.IsNullOrEmpty(cropData))
|
||||||
|
{
|
||||||
|
if (item.ProviderIds == null)
|
||||||
|
{
|
||||||
|
item.ProviderIds = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
item.ProviderIds["BlackBarCrop"] = cropData;
|
||||||
|
await _libraryManager.UpdateItemAsync(item, item, ItemUpdateType.MetadataEdit, cancellationToken);
|
||||||
_logger.LogInformation("Found black bars {Crop} in {Path}", cropData, path);
|
_logger.LogInformation("Found black bars {Crop} in {Path}", cropData, path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ for (( i=1; i<=$#; i++ )); do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [ -n ""$INPUT_FILE"" ]; then
|
if [ -n ""$INPUT_FILE"" ]; then
|
||||||
# Jellyfin przekazuje ścieżkę z prefiksem file: (np. file:""/home/..."").
|
CLEAN_PATH=$(echo ""$INPUT_FILE"" | tr -d '""' | sed 's/^file://')
|
||||||
# Shell usuwa cudzysłowy automatycznie – zostaje nam tylko file: do usunięcia.
|
|
||||||
CLEAN_PATH=""${{INPUT_FILE#file:}}""
|
|
||||||
|
|
||||||
CROP_DATA=$(curl -s --max-time 1 -G --data-urlencode ""Path=$CLEAN_PATH"" http://127.0.0.1:8096/BlackBarRemover/CropByPath)
|
CROP_DATA=$(curl -s --max-time 1 -G --data-urlencode ""Path=$CLEAN_PATH"" http://127.0.0.1:8096/BlackBarRemover/CropByPath)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user