mirror of https://github.com/jellyfin/jellyfin.git
Merge pull request #10067 from lonebyte/flac-hls-fixes
This commit is contained in:
commit
d5695efad9
|
@ -45,6 +45,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||||
private const string DefaultEventEncoderPreset = "superfast";
|
private const string DefaultEventEncoderPreset = "superfast";
|
||||||
private const TranscodingJobType TranscodingJobType = MediaBrowser.Controller.MediaEncoding.TranscodingJobType.Hls;
|
private const TranscodingJobType TranscodingJobType = MediaBrowser.Controller.MediaEncoding.TranscodingJobType.Hls;
|
||||||
|
|
||||||
|
private readonly Version _minFFmpegFlacInMp4 = new Version(6, 0);
|
||||||
|
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IDlnaManager _dlnaManager;
|
private readonly IDlnaManager _dlnaManager;
|
||||||
|
@ -1705,16 +1707,28 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||||
var audioCodec = _encodingHelper.GetAudioEncoder(state);
|
var audioCodec = _encodingHelper.GetAudioEncoder(state);
|
||||||
var bitStreamArgs = EncodingHelper.GetAudioBitStreamArguments(state, state.Request.SegmentContainer, state.MediaSource.Container);
|
var bitStreamArgs = EncodingHelper.GetAudioBitStreamArguments(state, state.Request.SegmentContainer, state.MediaSource.Container);
|
||||||
|
|
||||||
|
// opus, dts, truehd and flac (in FFmpeg 5 and older) are experimental in mp4 muxer
|
||||||
|
var strictArgs = string.Empty;
|
||||||
|
var actualOutputAudioCodec = state.ActualOutputAudioCodec;
|
||||||
|
if (string.Equals(actualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(actualOutputAudioCodec, "dts", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(actualOutputAudioCodec, "truehd", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| (string.Equals(actualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& _mediaEncoder.EncoderVersion < _minFFmpegFlacInMp4))
|
||||||
|
{
|
||||||
|
strictArgs = " -strict -2";
|
||||||
|
}
|
||||||
|
|
||||||
if (!state.IsOutputVideo)
|
if (!state.IsOutputVideo)
|
||||||
{
|
{
|
||||||
if (EncodingHelper.IsCopyCodec(audioCodec))
|
if (EncodingHelper.IsCopyCodec(audioCodec))
|
||||||
{
|
{
|
||||||
return "-acodec copy -strict -2" + bitStreamArgs;
|
return "-acodec copy" + bitStreamArgs + strictArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
var audioTranscodeParams = string.Empty;
|
var audioTranscodeParams = string.Empty;
|
||||||
|
|
||||||
audioTranscodeParams += "-acodec " + audioCodec + bitStreamArgs;
|
audioTranscodeParams += "-acodec " + audioCodec + bitStreamArgs + strictArgs;
|
||||||
|
|
||||||
var audioBitrate = state.OutputAudioBitrate;
|
var audioBitrate = state.OutputAudioBitrate;
|
||||||
var audioChannels = state.OutputAudioChannels;
|
var audioChannels = state.OutputAudioChannels;
|
||||||
|
@ -1746,17 +1760,6 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||||
return audioTranscodeParams;
|
return audioTranscodeParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dts, flac, opus and truehd are experimental in mp4 muxer
|
|
||||||
var strictArgs = string.Empty;
|
|
||||||
var actualOutputAudioCodec = state.ActualOutputAudioCodec;
|
|
||||||
if (string.Equals(actualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(actualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(actualOutputAudioCodec, "dts", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(actualOutputAudioCodec, "truehd", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
strictArgs = " -strict -2";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EncodingHelper.IsCopyCodec(audioCodec))
|
if (EncodingHelper.IsCopyCodec(audioCodec))
|
||||||
{
|
{
|
||||||
var videoCodec = _encodingHelper.GetVideoEncoder(state, _encodingOptions);
|
var videoCodec = _encodingHelper.GetVideoEncoder(state, _encodingOptions);
|
||||||
|
|
|
@ -200,13 +200,6 @@ public class DynamicHlsHelper
|
||||||
|
|
||||||
if (state.VideoStream is not null && state.VideoRequest is not null)
|
if (state.VideoStream is not null && state.VideoRequest is not null)
|
||||||
{
|
{
|
||||||
// Provide a workaround for the case issue between flac and fLaC.
|
|
||||||
var flacWaPlaylist = ApplyFlacCaseWorkaround(state, basicPlaylist.ToString());
|
|
||||||
if (!string.IsNullOrEmpty(flacWaPlaylist))
|
|
||||||
{
|
|
||||||
builder.Append(flacWaPlaylist);
|
|
||||||
}
|
|
||||||
|
|
||||||
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
|
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
|
||||||
|
|
||||||
// Provide SDR HEVC entrance for backward compatibility.
|
// Provide SDR HEVC entrance for backward compatibility.
|
||||||
|
@ -236,14 +229,7 @@ public class DynamicHlsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
|
var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
|
||||||
var sdrPlaylist = AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);
|
AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);
|
||||||
|
|
||||||
// Provide a workaround for the case issue between flac and fLaC.
|
|
||||||
flacWaPlaylist = ApplyFlacCaseWorkaround(state, sdrPlaylist.ToString());
|
|
||||||
if (!string.IsNullOrEmpty(flacWaPlaylist))
|
|
||||||
{
|
|
||||||
builder.Append(flacWaPlaylist);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the video codec
|
// Restore the video codec
|
||||||
state.OutputVideoCodec = "copy";
|
state.OutputVideoCodec = "copy";
|
||||||
|
@ -274,13 +260,6 @@ public class DynamicHlsHelper
|
||||||
state.VideoStream.Level = originalLevel;
|
state.VideoStream.Level = originalLevel;
|
||||||
var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField);
|
var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField);
|
||||||
builder.Append(newPlaylist);
|
builder.Append(newPlaylist);
|
||||||
|
|
||||||
// Provide a workaround for the case issue between flac and fLaC.
|
|
||||||
flacWaPlaylist = ApplyFlacCaseWorkaround(state, newPlaylist);
|
|
||||||
if (!string.IsNullOrEmpty(flacWaPlaylist))
|
|
||||||
{
|
|
||||||
builder.Append(flacWaPlaylist);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,16 +746,4 @@ public class DynamicHlsHelper
|
||||||
newValue.ToString(),
|
newValue.ToString(),
|
||||||
StringComparison.Ordinal);
|
StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ApplyFlacCaseWorkaround(StreamState state, string srcPlaylist)
|
|
||||||
{
|
|
||||||
if (!string.Equals(state.ActualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newPlaylist = srcPlaylist.Replace(",flac\"", ",fLaC\"", StringComparison.Ordinal);
|
|
||||||
|
|
||||||
return newPlaylist.Contains(",fLaC\"", StringComparison.Ordinal) ? newPlaylist : string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ using System.Text;
|
||||||
namespace Jellyfin.Api.Helpers;
|
namespace Jellyfin.Api.Helpers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hls Codec string helpers.
|
/// Helpers to generate HLS codec strings according to
|
||||||
|
/// <a href="https://datatracker.ietf.org/doc/html/rfc6381#section-3.3">RFC 6381 section 3.3</a>
|
||||||
|
/// and the <a href="https://mp4ra.org">MP4 Registration Authority</a>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class HlsCodecStringHelpers
|
public static class HlsCodecStringHelpers
|
||||||
{
|
{
|
||||||
|
@ -27,7 +29,7 @@ public static class HlsCodecStringHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Codec name for FLAC.
|
/// Codec name for FLAC.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string FLAC = "flac";
|
public const string FLAC = "fLaC";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Codec name for ALAC.
|
/// Codec name for ALAC.
|
||||||
|
@ -37,7 +39,7 @@ public static class HlsCodecStringHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Codec name for OPUS.
|
/// Codec name for OPUS.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string OPUS = "opus";
|
public const string OPUS = "Opus";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a MP3 codec string.
|
/// Gets a MP3 codec string.
|
||||||
|
|
Loading…
Reference in New Issue