Add support for Tizen via transcoding
Some checks failed
🏗️ Build Plugin / build (push) Failing after 15m44s
Latest Release / latest-release (push) Has been cancelled
🧪 Test Plugin / test (push) Has been cancelled
🚀 Release Plugin / build-and-release (push) Failing after 3m23s

This commit is contained in:
Duncan Tourolle 2026-05-03 10:40:11 +02:00
parent 86b22c69d7
commit 24f53ef13e
3 changed files with 6 additions and 20 deletions

View File

@ -160,7 +160,8 @@ public class StreamProxyController : ControllerBase
AddManifestCacheHeaders(actualItemId); AddManifestCacheHeaders(actualItemId);
_logger.LogDebug("Returning master manifest for item {ItemId} ({Length} bytes)", itemId, manifestContent.Length); _logger.LogDebug("Returning master manifest for item {ItemId} ({Length} bytes)", itemId, manifestContent.Length);
return Content(manifestContent, "application/vnd.apple.mpegurl; charset=utf-8"); // Use application/x-mpegURL for broader compatibility (Samsung AVPlay requires it)
return Content(manifestContent, "application/x-mpegURL; charset=utf-8");
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -231,7 +232,7 @@ public class StreamProxyController : ControllerBase
AddManifestCacheHeaders(actualItemId, isVariantManifest: true); AddManifestCacheHeaders(actualItemId, isVariantManifest: true);
_logger.LogDebug("Returning variant manifest for item {ItemId} ({Length} bytes)", itemId, rewrittenContent.Length); _logger.LogDebug("Returning variant manifest for item {ItemId} ({Length} bytes)", itemId, rewrittenContent.Length);
return Content(rewrittenContent, "application/vnd.apple.mpegurl; charset=utf-8"); return Content(rewrittenContent, "application/x-mpegURL; charset=utf-8");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -91,15 +91,15 @@ public class MediaSourceFactory : IMediaSourceFactory
Protocol = MediaProtocol.Http, Protocol = MediaProtocol.Http,
// Use "hls" to trigger hls.js player in web client // Use "hls" to trigger hls.js player in web client
Container = "hls", Container = "hls",
SupportsDirectStream = true, SupportsDirectStream = false,
SupportsDirectPlay = true, SupportsDirectPlay = true,
SupportsTranscoding = false, SupportsTranscoding = true,
IsRemote = true, IsRemote = true,
Type = MediaSourceType.Default, Type = MediaSourceType.Default,
RunTimeTicks = chapter.Duration > 0 ? TimeSpan.FromMilliseconds(chapter.Duration).Ticks : null, RunTimeTicks = chapter.Duration > 0 ? TimeSpan.FromMilliseconds(chapter.Duration).Ticks : null,
VideoType = VideoType.VideoFile, VideoType = VideoType.VideoFile,
IsInfiniteStream = isLiveStream, IsInfiniteStream = isLiveStream,
// Don't use RequiresOpening - it forces Jellyfin to transcode which breaks token auth // RequiresOpening = false: proxy handles auth directly, no need for Jellyfin to open the stream
RequiresOpening = false, RequiresOpening = false,
RequiresClosing = false, RequiresClosing = false,
// Disable probing - we provide stream info directly // Disable probing - we provide stream info directly

View File

@ -656,21 +656,6 @@ public class StreamProxyService : IStreamProxyService
// Rewrite the manifest to replace Akamai URLs with proxy URLs // Rewrite the manifest to replace Akamai URLs with proxy URLs
var rewrittenContent = RewriteManifestUrls(manifestContent, authenticatedUrl, baseProxyUrl); var rewrittenContent = RewriteManifestUrls(manifestContent, authenticatedUrl, baseProxyUrl);
// For live streams, inject #EXT-X-START to tell the player to start near the live edge
// Without this, players may start at the beginning of the sliding window and stutter
// as old segments get rotated out by the CDN
if (_streamMappings.TryGetValue(itemId, out var streamInfoForManifest) && streamInfoForManifest.IsLiveStream)
{
if (!rewrittenContent.Contains("#EXT-X-START", StringComparison.Ordinal))
{
rewrittenContent = rewrittenContent.Replace(
"#EXTM3U",
"#EXTM3U\n#EXT-X-START:TIME-OFFSET=-6,PRECISE=NO",
StringComparison.Ordinal);
_logger.LogDebug("Injected #EXT-X-START tag for live stream {ItemId}", itemId);
}
}
_logger.LogDebug("Rewritten manifest for item {ItemId} ({Length} bytes):\n{Content}", itemId, rewrittenContent.Length, rewrittenContent); _logger.LogDebug("Rewritten manifest for item {ItemId} ({Length} bytes):\n{Content}", itemId, rewrittenContent.Length, rewrittenContent);
return rewrittenContent; return rewrittenContent;
} }