Fix crop bounding box and limit defaults, setting reset=1
This commit is contained in:
@@ -4,8 +4,8 @@ namespace JellyfinPlugin.Configuration
|
|||||||
{
|
{
|
||||||
public class PluginConfiguration : BasePluginConfiguration
|
public class PluginConfiguration : BasePluginConfiguration
|
||||||
{
|
{
|
||||||
// Tolerancja detekcji czarnych pasów (domyślnie 0.15 czyli 15%)
|
// Tolerancja detekcji czarnych pasów (0.094 = domyślne 24/255)
|
||||||
public double CropDetectLimit { get; set; } = 0.15;
|
public double CropDetectLimit { get; set; } = 0.094;
|
||||||
|
|
||||||
// Czy wtyczka jest aktywna
|
// Czy wtyczka jest aktywna
|
||||||
public bool IsEnabled { get; set; } = true;
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ namespace JellyfinPlugin
|
|||||||
{
|
{
|
||||||
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
|
||||||
|
// Używamy domyślnego limitu ffmpeg (ok. 0.094), ewentualnie tego z configu jeśli użytkownik zmienił
|
||||||
string limitStr = limit.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
string limitStr = limit.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "ffmpeg",
|
FileName = "ffmpeg",
|
||||||
Arguments = $"-skip_frame nokey -i \"{filePath}\" -vf \"cropdetect=limit={limitStr}:round=16:reset=0\" -f null -",
|
// 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 -",
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
@@ -44,9 +47,39 @@ namespace JellyfinPlugin
|
|||||||
|
|
||||||
if (totalFrames == 0) return string.Empty;
|
if (totalFrames == 0) return string.Empty;
|
||||||
|
|
||||||
var bestCrop = crops.OrderByDescending(kvp => kvp.Value).FirstOrDefault().Key;
|
// Bierzemy pod uwagę tylko wymiary, które występują przez co najmniej 5% czasu filmu
|
||||||
|
// Dzięki temu ignorujemy jednosekundowe loga czy zaszumione klatki
|
||||||
return bestCrop ?? string.Empty;
|
var validCrops = crops.Where(kvp => (double)kvp.Value / totalFrames > 0.05).ToList();
|
||||||
|
if (!validCrops.Any())
|
||||||
|
{
|
||||||
|
validCrops = crops.OrderByDescending(kvp => kvp.Value).Take(1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tworzymy maksymalną obwiednię (Bounding Box) ze wszystkich WAŻNYCH kadrów
|
||||||
|
// Dzięki temu jeśli film to np. Interstellar (30% czasu w 16:9), kadr 16:9 zostanie zachowany
|
||||||
|
// i nie utniemy ważnych scen!
|
||||||
|
int minX = int.MaxValue, minY = int.MaxValue, maxXW = 0, maxYH = 0;
|
||||||
|
|
||||||
|
foreach (var kvp in validCrops)
|
||||||
|
{
|
||||||
|
var parts = kvp.Key.Split(':');
|
||||||
|
if (parts.Length == 4 &&
|
||||||
|
int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h) &&
|
||||||
|
int.TryParse(parts[2], out int x) && int.TryParse(parts[3], out int y))
|
||||||
|
{
|
||||||
|
minX = Math.Min(minX, x);
|
||||||
|
minY = Math.Min(minY, y);
|
||||||
|
maxXW = Math.Max(maxXW, x + w);
|
||||||
|
maxYH = Math.Max(maxYH, y + h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int finalW = maxXW - minX;
|
||||||
|
int finalH = maxYH - minY;
|
||||||
|
|
||||||
|
if (finalW <= 0 || finalH <= 0) return string.Empty;
|
||||||
|
|
||||||
|
return $"{finalW}:{finalH}:{minX}:{minY}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user