Files
blackBarRemover/JellyfinPlugin/WrapperGenerator.cs
T
2026-09-17 20:51:54 +02:00

190 lines
6.6 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace JellyfinPlugin
{
public class WrapperGenerator : IHostedService
{
private readonly ILogger<WrapperGenerator> _logger;
private readonly IApplicationPaths _appPaths;
private readonly IServerConfigurationManager _configManager;
public WrapperGenerator(ILogger<WrapperGenerator> logger, IApplicationPaths appPaths, IServerConfigurationManager configManager)
{
_logger = logger;
_appPaths = appPaths;
_configManager = configManager;
}
public Task StartAsync(CancellationToken cancellationToken)
{
GenerateAndSetWrapper();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private void GenerateAndSetWrapper()
{
try
{
var mode = Plugin.Instance!.Configuration.PlaybackMode;
if (mode == "Client")
{
// Jeżeli wybrano tylko klienta, nie nadpisujemy ffmpeg
return;
}
// Przygotowujemy zamianę pliku ffmpeg bezpośrednio w /usr/lib/jellyfin-ffmpeg/ffmpeg
string defaultFfmpeg = "/usr/lib/jellyfin-ffmpeg/ffmpeg";
string origFfmpeg = "/usr/lib/jellyfin-ffmpeg/ffmpeg.original";
string realFfmpegPath = origFfmpeg;
if (!File.Exists(origFfmpeg))
{
if (File.Exists(defaultFfmpeg))
{
try
{
File.Move(defaultFfmpeg, origFfmpeg);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Nie udało się przenieść {DefaultFfmpeg} do {OrigFfmpeg}", defaultFfmpeg, origFfmpeg);
realFfmpegPath = defaultFfmpeg;
}
}
else if (File.Exists("/usr/bin/ffmpeg"))
{
realFfmpegPath = "/usr/bin/ffmpeg";
}
}
string wrapperDir = Path.Combine(_appPaths.PluginsPath, "BlackBarRemover");
Directory.CreateDirectory(wrapperDir);
string wrapperPath = Path.Combine(wrapperDir, "ffmpeg");
string script = $@"#!/bin/bash
REAL_FFMPEG=""{realFfmpegPath}""
INPUT_FILE=""""
for (( i=1; i<=$#; i++ )); do
arg=""${{!i}}""
if [[ ""$arg"" == ""-i"" ]]; then
let next_idx=i+1
if [ $next_idx -le $# ]; then
INPUT_FILE=""${{!next_idx}}""
fi
break
fi
done
if [ -n ""$INPUT_FILE"" ]; then
CLEAN_PATH=$(echo ""$INPUT_FILE"" | tr -d '""' | sed 's/^file://')
CROP_DATA=$(curl -s --max-time 1 -G --data-urlencode ""Path=$CLEAN_PATH"" http://127.0.0.1:8096/BlackBarRemover/CropByPath)
if [ -n ""$CROP_DATA"" ] && [ ""$CROP_DATA"" != """" ]; then
# Modyfikujemy argumenty w locie
declare -a NEW_ARGS
HAS_VF=0
IS_COPY=0
for (( i=1; i<=$#; i++ )); do
arg=""${{!i}}""
if [[ ""$arg"" == ""copy"" ]]; then
let prev_idx=i-1
prev_arg=""""
if [ $prev_idx -gt 0 ]; then
prev_arg=""${{!prev_idx}}""
fi
if [[ ""$prev_arg"" == *codec:v* ]] || [[ ""$prev_arg"" == *-c:v* ]] || [[ ""$prev_arg"" == *-vcodec* ]]; then
IS_COPY=1
fi
fi
if [[ ""$arg"" == ""-vf"" ]]; then
HAS_VF=1
NEW_ARGS+=(""-vf"")
next_arg=""""
let next_idx=i+1
if [ $next_idx -le $# ]; then
next_arg=""${{!next_idx}}""
fi
NEW_ARGS+=(""$next_arg,crop=$CROP_DATA"")
let i++
continue
fi
NEW_ARGS+=(""$arg"")
done
# Jeżeli Jellyfin nadal upiera się przy copy, nie możemy wstrzyknąć filtra crop (bo zcrashuje FFmpega)
if [ $IS_COPY -eq 1 ]; then
exec ""$REAL_FFMPEG"" ""$@""
exit 0
fi
if [ $HAS_VF -eq 0 ]; then
NEW_ARGS+=(""-vf"")
NEW_ARGS+=(""crop=$CROP_DATA"")
fi
exec ""$REAL_FFMPEG"" ""${{NEW_ARGS[@]}}""
exit 0
fi
fi
exec ""$REAL_FFMPEG"" ""$@""
";
File.WriteAllText(wrapperPath, script);
if (File.Exists(origFfmpeg) || defaultFfmpeg != origFfmpeg)
{
try
{
File.WriteAllText(defaultFfmpeg, script);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Nie udało się zapisać skryptu wrappera do {DefaultFfmpeg}", defaultFfmpeg);
}
}
if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD() || OperatingSystem.IsMacOS())
{
string[] pathsToChmod = new[] { wrapperPath, defaultFfmpeg };
foreach (var path in pathsToChmod)
{
if (!File.Exists(path)) continue;
try
{
File.SetUnixFileMode(path, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherExecute);
}
catch
{
var proc = System.Diagnostics.Process.Start("chmod", $"+x \"{path}\"");
proc?.WaitForExit();
}
}
}
_logger.LogInformation("Wygenerowano skrypt FFmpeg Wrapper w lokalizacji: {Path} oraz {DefaultFfmpeg}", wrapperPath, defaultFfmpeg);
}
catch (Exception ex)
{
_logger.LogError(ex, "Błąd podczas generowania i ustawiania skryptu FFmpeg wrapper.");
}
}
}
}