diff --git a/JellyfinPlugin/Api/BlackBarService.cs b/JellyfinPlugin/Api/BlackBarService.cs index 7d7f242..cd47316 100644 --- a/JellyfinPlugin/Api/BlackBarService.cs +++ b/JellyfinPlugin/Api/BlackBarService.cs @@ -71,9 +71,40 @@ namespace JellyfinPlugin.Api let currentItemId = null; let interceptedItemId = null; + function isTranscoding() { + try { + if (window.playbackManager) { + const currentPlayer = window.playbackManager.getCurrentPlayer(); + if (currentPlayer && typeof currentPlayer.getPlayerState === 'function') { + const state = currentPlayer.getPlayerState(); + if (state && state.PlayMethod) { + return state.PlayMethod === 'Transcode' || state.PlayMethod === 'DirectStream'; + } + } + } + } catch (e) {} + + const video = document.querySelector('video'); + if (video && video.src) { + const src = video.src.toLowerCase(); + if (src.includes('transcode') || src.includes('.m3u8') || src.includes('transcodereasons')) { + return true; + } + } + return false; + } + function applyCrop(cropData) { const video = document.querySelector('video'); if (!video) return; + + if (isTranscoding()) { + console.log('Black Bar Remover: Video is transcoded by server, skipping CSS crop.'); + video.style.clipPath = ''; + video.style.transform = ''; + return; + } + const parts = cropData.split(':'); if (parts.length === 4) { const w = parseInt(parts[0]); diff --git a/JellyfinPlugin/Configuration/PluginConfiguration.cs b/JellyfinPlugin/Configuration/PluginConfiguration.cs index 610cf9e..2fafcea 100644 --- a/JellyfinPlugin/Configuration/PluginConfiguration.cs +++ b/JellyfinPlugin/Configuration/PluginConfiguration.cs @@ -10,7 +10,7 @@ namespace JellyfinPlugin.Configuration // Czy wtyczka jest aktywna public bool IsEnabled { get; set; } = true; - // Tryb odtwarzania: "Server" (FFmpeg wrapper), "Client" (CSS injection w Web UI), "Both" (Obydwa naraz) - public string PlaybackMode { get; set; } = "Both"; + // 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"; } } diff --git a/JellyfinPlugin/Configuration/configPage.html b/JellyfinPlugin/Configuration/configPage.html index 6be49a6..f500045 100644 --- a/JellyfinPlugin/Configuration/configPage.html +++ b/JellyfinPlugin/Configuration/configPage.html @@ -26,11 +26,11 @@
-
Choose how the plugin should remove black bars. Server option forces transcoding (CPU/GPU load), Client option is lightweight but only works in web browsers.
+
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.
@@ -53,7 +53,9 @@ ApiClient.getPluginConfiguration(BlackBarRemoverConfig.pluginUniqueId).then(function (config) { $('#chkEnablePlugin', page).prop('checked', config.IsEnabled !== false); $('#txtCropLimit', page).val(config.CropDetectLimit || 0.094); - $('#selectPlaybackMode', page).val(config.PlaybackMode || "Both"); + var mode = config.PlaybackMode || "Auto"; + if (mode === "Both") mode = "Auto"; + $('#selectPlaybackMode', page).val(mode); Dashboard.hideLoadingMsg(); }); }); diff --git a/JellyfinPlugin/PlaybackInfoInterceptorStartupFilter.cs b/JellyfinPlugin/PlaybackInfoInterceptorStartupFilter.cs index 047b2d8..3fe3c2f 100644 --- a/JellyfinPlugin/PlaybackInfoInterceptorStartupFilter.cs +++ b/JellyfinPlugin/PlaybackInfoInterceptorStartupFilter.cs @@ -60,6 +60,14 @@ namespace JellyfinPlugin return; } + var isAutoMode = config.PlaybackMode == "Auto" || config.PlaybackMode == "Both"; + if (isAutoMode && IsJellyfinWebClient(context)) + { + // W trybie Auto dla przeglądarki Web pozwalamy na Direct Play (przycięcie wykona skrypt CSS w przeglądarce). + await nextMw().ConfigureAwait(false); + return; + } + // --- HLS STREAM QUERY REWRITE --- // If the client requests the m3u8 playlist, we simply tell Jellyfin NOT to allow video stream copy. // This elegantly forces transcoding for the BEST supported codec without breaking FFmpeg tags/filters! @@ -147,5 +155,43 @@ namespace JellyfinPlugin await nextMw().ConfigureAwait(false); } + + private static bool IsJellyfinWebClient(HttpContext context) + { + if (context.Request.Headers.TryGetValue("X-Emby-Authorization", out var authHeader) || + context.Request.Headers.TryGetValue("Authorization", out authHeader)) + { + var authStr = authHeader.ToString(); + if (authStr.Contains("Client=\"Jellyfin Web\"", StringComparison.OrdinalIgnoreCase) || + authStr.Contains("Client=\"Jellyfin%20Web\"", StringComparison.OrdinalIgnoreCase) || + authStr.Contains("Client=Jellyfin Web", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + if (context.Request.Headers.TryGetValue("User-Agent", out var uaHeader)) + { + var ua = uaHeader.ToString(); + if (ua.Contains("JellyfinMediaPlayer", StringComparison.OrdinalIgnoreCase) || + ua.Contains("Jellyfin-Android", StringComparison.OrdinalIgnoreCase) || + ua.Contains("ExoPlayer", StringComparison.OrdinalIgnoreCase) || + ua.Contains("okhttp", StringComparison.OrdinalIgnoreCase) || + ua.Contains("Kodi", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (ua.Contains("Mozilla", StringComparison.OrdinalIgnoreCase) || + ua.Contains("Chrome", StringComparison.OrdinalIgnoreCase) || + ua.Contains("Safari", StringComparison.OrdinalIgnoreCase) || + ua.Contains("Firefox", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } } } diff --git a/README.md b/README.md index 5fd5f83..5bd46b2 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,21 @@ This plugin has been verified and tested on: ### Method 3: Building from Source 1. Clone this repository. -2. Build the plugin using the .NET 9 SDK: +2. Ensure you have the **.NET 9.0 SDK** and/or **.NET 10.0 SDK** installed (the project multi-targets both `net9.0` and `net10.0`). +3. Build the plugin for all targets: ```bash dotnet build JellyfinPlugin/JellyfinPlugin.csproj -c Release ``` -3. Copy the compiled DLLs from `JellyfinPlugin/bin/Release/net9.0/` into a new folder named `BlackBarRemover` inside your Jellyfin plugins directory. -4. Restart the Jellyfin server. + Or build for a specific target framework: + ```bash + # For Jellyfin 10.11 (.NET 9.0) + dotnet build JellyfinPlugin/JellyfinPlugin.csproj -c Release -f net9.0 + + # For Jellyfin 12.0 / 13.0 Unstable (.NET 10.0) + dotnet build JellyfinPlugin/JellyfinPlugin.csproj -c Release -f net10.0 + ``` +4. Copy the compiled DLLs from `JellyfinPlugin/bin/Release/net9.0/` (for Jellyfin 10.11) or `JellyfinPlugin/bin/Release/net10.0/` (for Jellyfin 12.0+) into a new folder named `BlackBarRemover` inside your Jellyfin plugins directory (e.g., `/var/lib/jellyfin/plugins/BlackBarRemover/`). +5. Restart the Jellyfin server. ### Configuration & Initial Scan