diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index 9941c9f6e6..6b1618421d 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -1412,7 +1412,7 @@ namespace Jellyfin.Api.Controllers
return string.Format(
CultureInfo.InvariantCulture,
- "{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -max_muxing_queue_size {6} -f hls -max_delay 5000000 -hls_time {7} -individual_header_trailer 0 -hls_segment_type {8} -start_number {9} -hls_segment_filename \"{10}\" -hls_playlist_type vod -hls_list_size 0 -y \"{11}\"",
+ "{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts 0 -max_muxing_queue_size {6} -f hls -max_delay 5000000 -hls_time {7} -individual_header_trailer 0 -hls_segment_type {8} -start_number {9} -hls_segment_filename \"{10}\" -hls_playlist_type vod -hls_list_size 0 -y \"{11}\"",
inputModifier,
_encodingHelper.GetInputArgument(state, encodingOptions),
threads,
@@ -1576,7 +1576,9 @@ namespace Jellyfin.Api.Controllers
args += " " + gopArg;
}
else if (string.Equals(codec, "libx264", StringComparison.OrdinalIgnoreCase)
- || string.Equals(codec, "libx265", StringComparison.OrdinalIgnoreCase))
+ || string.Equals(codec, "libx265", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "hevc_vaapi", StringComparison.OrdinalIgnoreCase))
{
args += " " + keyFrameArg;
}
diff --git a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
index 3d7a9d9a01..4999fcc62f 100644
--- a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
+++ b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
@@ -9,13 +9,38 @@ namespace Jellyfin.Api.Helpers
///
public static class HlsCodecStringHelpers
{
+ ///
+ /// Codec name for MP3.
+ ///
+ public const string MP3 = "mp4a.40.34";
+
+ ///
+ /// Codec name for AC-3.
+ ///
+ public const string AC3 = "mp4a.a5";
+
+ ///
+ /// Codec name for E-AC-3.
+ ///
+ public const string EAC3 = "mp4a.a6";
+
+ ///
+ /// Codec name for FLAC.
+ ///
+ public const string FLAC = "fLaC";
+
+ ///
+ /// Codec name for ALAC.
+ ///
+ public const string ALAC = "alac";
+
///
/// Gets a MP3 codec string.
///
/// MP3 codec string.
public static string GetMP3String()
{
- return "mp4a.40.34";
+ return MP3;
}
///
@@ -40,6 +65,42 @@ namespace Jellyfin.Api.Helpers
return result.ToString();
}
+ ///
+ /// Gets an AC-3 codec string.
+ ///
+ /// AC-3 codec string.
+ public static string GetAC3String()
+ {
+ return AC3;
+ }
+
+ ///
+ /// Gets an E-AC-3 codec string.
+ ///
+ /// E-AC-3 codec string.
+ public static string GetEAC3String()
+ {
+ return EAC3;
+ }
+
+ ///
+ /// Gets an FLAC codec string.
+ ///
+ /// FLAC codec string.
+ public static string GetFLACString()
+ {
+ return FLAC;
+ }
+
+ ///
+ /// Gets an ALAC codec string.
+ ///
+ /// ALAC codec string.
+ public static string GetALACString()
+ {
+ return ALAC;
+ }
+
///
/// Gets a H.264 codec string.
///
@@ -104,41 +165,5 @@ namespace Jellyfin.Api.Helpers
return result.ToString();
}
-
- ///
- /// Gets an AC-3 codec string.
- ///
- /// AC-3 codec string.
- public static string GetAC3String()
- {
- return "mp4a.a5";
- }
-
- ///
- /// Gets an E-AC-3 codec string.
- ///
- /// E-AC-3 codec string.
- public static string GetEAC3String()
- {
- return "mp4a.a6";
- }
-
- ///
- /// Gets an FLAC codec string.
- ///
- /// FLAC codec string.
- public static string GetFLACString()
- {
- return "fLaC";
- }
-
- ///
- /// Gets an ALAC codec string.
- ///
- /// ALAC codec string.
- public static string GetALACString()
- {
- return "alac";
- }
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 87670e2eb3..6e348f1e65 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -662,6 +662,10 @@ namespace MediaBrowser.Controller.MediaEncoding
if (string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase))
{
+ // Transcode to level 5.0 and lower for maximum compatibility
+ // level 5.0 is suitable for up to 4k 30fps hevc encoding, otherwise let the encoder to handle it
+ // https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding_tiers_and_levels
+ // MaxLumaSampleRate = 3840*2160*30 = 248832000 < 267386880,
if (requestLevel >= 150)
{
return "150";
@@ -3293,7 +3297,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps)
{
- args += " -copyts -avoid_negative_ts disabled -start_at_zero";
+ args += " -copyts -avoid_negative_ts 0 -start_at_zero";
}
if (!state.RunTimeTicks.HasValue)
@@ -3341,7 +3345,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -copyts";
}
- args += " -avoid_negative_ts disabled";
+ args += " -avoid_negative_ts 0";
if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream))
{