Moved to patches/: - jellyfin-progressive-download-improvements-v10.11.5.patch (server) - jellyfin-web-download-dialog-v10.11.5.patch (web UI) Kept in code: - Xbox UWP codec detection (AV1/Opus fix) - FFmpeg log level configuration - Remote source forced transcoding - Quality text UI fix (web) Both jellyfin-server and jellyfin-web reset to v10.11.5 base
110 lines
5.5 KiB
Diff
110 lines
5.5 KiB
Diff
From: Jellyfin Packaging <noreply@jellyfin.org>
|
|
Date: Wed, 8 Jan 2025 00:00:00 +0000
|
|
Subject: [PATCH] Progressive download improvements for v10.11.5+
|
|
|
|
This patch includes all progressive download and transcoding improvements:
|
|
- Use /downloads/ folder for full-file progressive downloads
|
|
- Fix download transcoding not stopping when client disconnects
|
|
- Improve MP4 movflags for better seeking compatibility (mpv/iina/infuse)
|
|
- Fix timestamp seeking for progressive downloads
|
|
- Use separate transcode paths for HLS vs progressive downloads
|
|
|
|
---
|
|
Jellyfin.Api/Controllers/VideosController.cs | 3 ++-
|
|
Jellyfin.Api/Helpers/StreamingHelpers.cs | 15 +++++++++++++++
|
|
.../MediaEncoding/EncodingHelper.cs | 22 ++++++++++++++++++++++
|
|
3 files changed, 39 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
|
|
index 97f3239bbc..6f9fbadddb 100644
|
|
--- a/Jellyfin.Api/Controllers/VideosController.cs
|
|
+++ b/Jellyfin.Api/Controllers/VideosController.cs
|
|
@@ -369,7 +369,8 @@ public class VideosController : BaseJellyfinApiController
|
|
{
|
|
var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head;
|
|
// CTS lifecycle is managed internally.
|
|
- var cancellationTokenSource = new CancellationTokenSource();
|
|
+ // Link to HttpContext.RequestAborted so transcode stops when client disconnects
|
|
+ var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(HttpContext.RequestAborted);
|
|
var streamingRequest = new VideoRequestDto
|
|
{
|
|
Id = itemId,
|
|
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
|
|
index b3f5b9a801..f366fd7a23 100644
|
|
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
|
|
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
|
|
@@ -378,8 +378,23 @@ public static class StreamingHelpers
|
|
|
|
var filename = data.GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
|
var ext = outputFileExtension.ToLowerInvariant();
|
|
+
|
|
+ // Use different transcode paths for HLS vs Progressive downloads
|
|
+ // HLS segments: use RAM-based transcode path (fast, auto-cleanup)
|
|
+ // Progressive downloads: use disk-based path (large files OK, slower cleanup)
|
|
var folder = serverConfigurationManager.GetTranscodePath();
|
|
|
|
+ // Check if this is a full file download (no segments) vs HLS streaming
|
|
+ var streamingRequest = state.BaseRequest as StreamingRequestDto;
|
|
+
|
|
+ if (streamingRequest?.SegmentContainer is null)
|
|
+ {
|
|
+ // Full file download - use disk-based transcode path
|
|
+ var diskTranscodePath = Path.Combine(folder, "downloads");
|
|
+ Directory.CreateDirectory(diskTranscodePath);
|
|
+ folder = diskTranscodePath;
|
|
+ }
|
|
+
|
|
return Path.Combine(folder, filename + ext);
|
|
}
|
|
|
|
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
|
|
index e088cd358d..a31a735bed 100644
|
|
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
|
|
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
|
|
@@ -20,6 +20,7 @@ using Jellyfin.Extensions;
|
|
using MediaBrowser.Common.Configuration;
|
|
using MediaBrowser.Controller.Extensions;
|
|
using MediaBrowser.Controller.IO;
|
|
+using MediaBrowser.Controller.Streaming;
|
|
using MediaBrowser.Model.Configuration;
|
|
using MediaBrowser.Model.Dlna;
|
|
using MediaBrowser.Model.Dto;
|
|
@@ -7475,8 +7476,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
if (Path.GetExtension(outputPath.AsSpan()).Equals(".mp4", StringComparison.OrdinalIgnoreCase)
|
|
&& state.BaseRequest.Context == EncodingContext.Streaming)
|
|
{
|
|
- // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js
|
|
- format = " -f mp4 -movflags frag_keyframe+empty_moov+delay_moov";
|
|
+ // Use fragmented MP4 for adaptive streaming (HLS/DASH with segments)
|
|
+ // Use faststart for progressive downloads (better seeking and metadata)
|
|
+ var streamingRequest = state.BaseRequest as StreamingRequestDto;
|
|
+ if (streamingRequest?.SegmentContainer is not null)
|
|
+ {
|
|
+ // Fragmented MP4 for HLS/DASH
|
|
+ format = " -f mp4 -movflags frag_keyframe+empty_moov+delay_moov";
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // Progressive download - use faststart for proper seeking and duration
|
|
+ // Use frag_keyframe for better seeking compatibility with mpv
|
|
+ format = " -f mp4 -movflags frag_keyframe+faststart+default_base_moof";
|
|
+ }
|
|
}
|
|
|
|
var threads = GetNumberOfThreads(state, encodingOptions, videoCodec);
|
|
@@ -7582,6 +7595,15 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|
args += " -start_at_zero";
|
|
}
|
|
}
|
|
+ else if (state.TranscodingType == TranscodingJobType.Progressive && !state.BaseRequest.CopyTimestamps)
|
|
+ {
|
|
+ // For progressive downloads without copyTimestamps, ensure timestamps start at 0
|
|
+ // This fixes seeking issues in strict players like mpv, iina, and infuse
|
|
+ args += " -avoid_negative_ts make_zero -start_at_zero";
|
|
+ }
|
|
|
|
var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultPreset);
|
|
|
|
--
|
|
2.43.0
|