From eca9bf41bcf536708ad74236793b363db3af1e4d Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sat, 16 Mar 2024 03:40:14 +0800 Subject: Add TranscodingSegmentCleaner to replace ffmpeg's hlsenc deletion FFmpeg deletes segments based on its own transcoding progress, but we need to delete segments based on client download progress. Since disk and GPU speeds vary, using hlsenc's built-in deletion will result in premature deletion of some segments. As a consequence, the server has to constantly respin new ffmpeg instances, resulting in choppy video playback. Signed-off-by: nyanmisaka --- .../Transcoding/TranscodeManager.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs index 8bace15c6..2a72cacdc 100644 --- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs +++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs @@ -546,6 +546,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable if (!transcodingJob.HasExited) { StartThrottler(state, transcodingJob); + StartSegmentCleaner(state, transcodingJob); } else if (transcodingJob.ExitCode != 0) { @@ -573,6 +574,22 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable && state.IsInputVideo && state.VideoType == VideoType.VideoFile; + private void StartSegmentCleaner(StreamState state, TranscodingJob transcodingJob) + { + if (EnableSegmentCleaning(state)) + { + transcodingJob.TranscodingSegmentCleaner = new TranscodingSegmentCleaner(transcodingJob, _loggerFactory.CreateLogger(), _serverConfigurationManager, _fileSystem, _mediaEncoder, state.SegmentLength); + transcodingJob.TranscodingSegmentCleaner.Start(); + } + } + + private static bool EnableSegmentCleaning(StreamState state) + => state.InputProtocol is MediaProtocol.File or MediaProtocol.Http + && state.IsInputVideo + && state.TranscodingType == TranscodingJobType.Hls + && state.RunTimeTicks.HasValue + && state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks; + private TranscodingJob OnTranscodeBeginning( string path, string? playSessionId, -- cgit v1.2.3 From 557b8f0c7879261d2dc8268e77836fd6efb7feb8 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sun, 17 Mar 2024 20:45:00 +0800 Subject: Apply suggestions from code review Drop the unnecessary initial capacity from the list. Signed-off-by: nyanmisaka --- MediaBrowser.Controller/MediaEncoding/TranscodingSegmentCleaner.cs | 2 +- MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/TranscodingSegmentCleaner.cs b/MediaBrowser.Controller/MediaEncoding/TranscodingSegmentCleaner.cs index a6d812873..67bfcb02f 100644 --- a/MediaBrowser.Controller/MediaEncoding/TranscodingSegmentCleaner.cs +++ b/MediaBrowser.Controller/MediaEncoding/TranscodingSegmentCleaner.cs @@ -156,7 +156,7 @@ public class TranscodingSegmentCleaner : IDisposable } catch (IOException ex) { - (exs ??= new List(4)).Add(ex); + (exs ??= new List()).Add(ex); _logger.LogDebug(ex, "Error deleting HLS segment file {Path}", file); } } diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs index 2a72cacdc..499e5287a 100644 --- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs +++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs @@ -321,7 +321,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable } catch (IOException ex) { - (exs ??= new List(4)).Add(ex); + (exs ??= new List()).Add(ex); _logger.LogError(ex, "Error deleting HLS file {Path}", file); } } -- cgit v1.2.3 From ae7c0c83e9f7b5e35ac067f09a92d10d33407219 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sun, 17 Mar 2024 21:30:42 +0800 Subject: Bump the required minimum ffmpeg version to 4.4 Signed-off-by: nyanmisaka --- .../MediaEncoding/EncodingHelper.cs | 3 +-- .../Encoder/EncoderValidator.cs | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5daa03935..cdaa6a6cd 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -51,7 +51,6 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly Version _minFFmpegOclCuTonemapMode = new Version(5, 1, 3); private readonly Version _minFFmpegSvtAv1Params = new Version(5, 1); private readonly Version _minFFmpegVaapiH26xEncA53CcSei = new Version(6, 0); - private readonly Version _minFFmpegAutoscaleOption = new Version(4, 4); private readonly Version _minFFmpegReadrateOption = new Version(5, 0); private static readonly string[] _videoProfilesH264 = new[] @@ -1223,7 +1222,7 @@ namespace MediaBrowser.Controller.MediaEncoding // Disable auto inserted SW scaler for HW decoders in case of changed resolution. var isSwDecoder = string.IsNullOrEmpty(GetHardwareVideoDecoder(state, options)); - if (!isSwDecoder && _mediaEncoder.EncoderVersion >= _minFFmpegAutoscaleOption) + if (!isSwDecoder) { arg.Append(" -noautoscale"); } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 6549125d3..6579f1abe 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -146,17 +146,18 @@ namespace MediaBrowser.MediaEncoding.Encoder { 5, new string[] { "overlay_vulkan", "Action to take when encountering EOF from secondary input" } } }; - // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below + // These are the library versions that corresponds to our minimum ffmpeg version 4.4 according to the version table below + // Refers to the versions in https://ffmpeg.org/download.html private static readonly Dictionary _ffmpegMinimumLibraryVersions = new Dictionary { - { "libavutil", new Version(56, 14) }, - { "libavcodec", new Version(58, 18) }, - { "libavformat", new Version(58, 12) }, - { "libavdevice", new Version(58, 3) }, - { "libavfilter", new Version(7, 16) }, - { "libswscale", new Version(5, 1) }, - { "libswresample", new Version(3, 1) }, - { "libpostproc", new Version(55, 1) } + { "libavutil", new Version(56, 70) }, + { "libavcodec", new Version(58, 134) }, + { "libavformat", new Version(58, 76) }, + { "libavdevice", new Version(58, 13) }, + { "libavfilter", new Version(7, 110) }, + { "libswscale", new Version(5, 9) }, + { "libswresample", new Version(3, 9) }, + { "libpostproc", new Version(55, 9) } }; private readonly ILogger _logger; @@ -176,7 +177,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // When changing this, also change the minimum library versions in _ffmpegMinimumLibraryVersions - public static Version MinVersion { get; } = new Version(4, 0); + public static Version MinVersion { get; } = new Version(4, 4); public static Version? MaxVersion { get; } = null; -- cgit v1.2.3