Automate FFmpeg wrapper configuration

This commit is contained in:
2026-09-17 14:23:20 +02:00
parent 904aada05d
commit 25ccafc2a4
3 changed files with 60 additions and 36 deletions
+58 -31
View File
@@ -1,11 +1,11 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Plugins;
using Microsoft.Extensions.Logging;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace JellyfinPlugin
{
@@ -13,16 +13,18 @@ namespace JellyfinPlugin
{
private readonly ILogger<WrapperGenerator> _logger;
private readonly IApplicationPaths _appPaths;
private readonly IServerConfigurationManager _configManager;
public WrapperGenerator(ILogger<WrapperGenerator> logger, IApplicationPaths appPaths)
public WrapperGenerator(ILogger<WrapperGenerator> logger, IApplicationPaths appPaths, IServerConfigurationManager configManager)
{
_logger = logger;
_appPaths = appPaths;
_configManager = configManager;
}
public Task StartAsync(CancellationToken cancellationToken)
{
GenerateWrapper();
GenerateAndSetWrapper();
return Task.CompletedTask;
}
@@ -31,45 +33,67 @@ namespace JellyfinPlugin
return Task.CompletedTask;
}
private void GenerateWrapper()
private void GenerateAndSetWrapper()
{
try
{
var mode = Plugin.Instance!.Configuration.PlaybackMode;
if (mode == "Client")
{
// Jeżeli wybrano tylko klienta, nie nadpisujemy ffmpeg
return;
}
// Pobieramy obecną konfigurację kodowania
var encodingConfig = _configManager.GetConfiguration("encoding");
if (encodingConfig == null) return;
// Używamy dynamic, aby ominąć potrzebę rzutowania na konkretny, wewnętrzny typ Jellyfin (EncodingOptions)
dynamic dynConfig = encodingConfig;
string currentFfmpegPath = dynConfig.EncoderAppPath ?? "/usr/lib/jellyfin-ffmpeg/ffmpeg";
string wrapperDir = Path.Combine(_appPaths.PluginsPath, "BlackBarRemover");
Directory.CreateDirectory(wrapperDir);
string wrapperPath = Path.Combine(wrapperDir, "ffmpeg-wrapper.sh");
string script = @"#!/bin/bash
# Zmienna przechowująca ścieżkę do prawdziwego FFmpeg Jellyfina (zmień jeśli trzeba)
REAL_FFMPEG=""/usr/lib/jellyfin-ffmpeg/ffmpeg""
// Jeśli obecna ścieżka to już nasz wrapper, nie robimy pętli w nieskończoność.
// Znajdujemy poprzednio zapisaną prawdziwą ścieżkę z pliku.
string realFfmpegPath = currentFfmpegPath;
if (currentFfmpegPath == wrapperPath)
{
if (File.Exists(wrapperPath))
{
var lines = File.ReadAllLines(wrapperPath);
foreach (var line in lines)
{
if (line.StartsWith("REAL_FFMPEG="))
{
realFfmpegPath = line.Split('=')[1].Trim('"');
break;
}
}
}
if (realFfmpegPath == wrapperPath) realFfmpegPath = "/usr/lib/jellyfin-ffmpeg/ffmpeg";
}
string script = $@"#!/bin/bash
# Zmienna przechowująca ścieżkę do prawdziwego FFmpeg Jellyfina
REAL_FFMPEG=""{realFfmpegPath}""
# Znajdujemy ścieżkę pliku wejściowego (argument po -i)
INPUT_FILE=""""
for i in ""${!@}""; do
if [[ ""${@:$i:1}"" == ""-i"" ]]; then
INPUT_FILE=""${@:$i+1:1}""
for i in ""${{!@}}""; do
if [[ ""${{@:$i:1}}"" == ""-i"" ]]; then
INPUT_FILE=""${{@:$i+1:1}}""
break
fi
done
# Pobieramy crop z API naszej wtyczki
if [ -n ""$INPUT_FILE"" ]; then
# Jellyfin lokalnie słucha na 8096, odpytujemy API o crop
CROP_DATA=$(curl -s --max-time 1 -G --data-urlencode ""Path=$INPUT_FILE"" http://127.0.0.1:8096/BlackBarRemover/CropByPath)
if [ -n ""$CROP_DATA"" ] && [ ""$CROP_DATA"" != """" ]; then
# Znaleziono crop! Wstrzykujemy filtr crop=W:H:X:Y do argumentów
# Dodajemy -vf crop przed argumentami wyjścia
NEW_ARGS=()
for arg in ""$@""; do
# Prosta iniekcja, w realnym środowisku szukamy gdzie wkleić -vf, zazwyczaj przed plikiem wyjściowym.
# Jellyfin sprzętowy tworzy filtry z -filter_complex, w softwareowym z -vf.
NEW_ARGS+=(""$arg"")
done
# Uruchamiamy ffmpeg z crop
# UWAGA: to jest uproszczenie. Prawdziwy wrapper IntroSkipper musi łączyć filtry.
# W tym MVP dodajemy prosty filter:
exec ""$REAL_FFMPEG"" ""$@"" -vf ""crop=$CROP_DATA""
exit 0
fi
@@ -80,22 +104,25 @@ exec ""$REAL_FFMPEG"" ""$@""
";
File.WriteAllText(wrapperPath, script);
// Nadajemy uprawnienia do wykonywania w systemach Linux (używając shella)
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
System.Diagnostics.Process.Start("chmod", $"+x \"{wrapperPath}\"");
}
_logger.LogInformation("Wygenerowano skrypt FFmpeg Wrapper w lokalizacji: {Path}", wrapperPath);
// Teraz automagicznie podmieniamy ścieżkę w Jellyfin!
if (dynConfig.EncoderAppPath != wrapperPath)
{
dynConfig.EncoderAppPath = wrapperPath;
_configManager.SaveConfiguration("encoding", encodingConfig);
_logger.LogInformation("Automatycznie zmieniono ścieżkę FFmpeg w konfiguracji Jellyfin na wrapper wtyczki.");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Błąd podczas generowania skryptu FFmpeg wrapper.");
_logger.LogError(ex, "Błąd podczas generowania i ustawiania skryptu FFmpeg wrapper.");
}
}
public void Dispose()
{
}
}
}