diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
index 26402c002e..69dc4e1ec5 100644
--- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
+++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
@@ -204,6 +204,13 @@ namespace Jellyfin.Api.Helpers
if (state.VideoStream != null && state.VideoRequest != 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();
// Provide SDR HEVC entrance for backward compatibility.
@@ -221,26 +228,26 @@ namespace Jellyfin.Api.Helpers
var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main");
sdrVideoUrl += "&AllowVideoStreamCopy=false";
- var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
- var sdrOutputAudioBitrate = 0;
- if (EncodingHelper.LosslessAudioCodecs.Contains(state.VideoRequest.AudioCodec, StringComparison.OrdinalIgnoreCase))
- {
- sdrOutputAudioBitrate = state.AudioStream.BitRate ?? 0;
- }
- else
- {
- sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream, state.OutputAudioChannels) ?? 0;
- }
-
- var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
- var sdrPlaylist = 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);
- }
+ var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
+ var sdrOutputAudioBitrate = 0;
+ if (EncodingHelper.LosslessAudioCodecs.Contains(state.VideoRequest.AudioCodec, StringComparison.OrdinalIgnoreCase))
+ {
+ sdrOutputAudioBitrate = state.AudioStream.BitRate ?? 0;
+ }
+ else
+ {
+ sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream, state.OutputAudioChannels) ?? 0;
+ }
+
+ var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
+ var sdrPlaylist = 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
state.OutputVideoCodec = "copy";
@@ -270,6 +277,13 @@ namespace Jellyfin.Api.Helpers
state.VideoStream.Level = originalLevel;
var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField);
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);
+ }
}
}
@@ -628,6 +642,11 @@ namespace Jellyfin.Api.Helpers
return HlsCodecStringHelpers.GetALACString();
}
+ if (string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
+ {
+ return HlsCodecStringHelpers.GetOPUSString();
+ }
+
return string.Empty;
}
@@ -726,7 +745,19 @@ namespace Jellyfin.Api.Helpers
return oldPlaylist.Replace(
oldValue.ToString(),
newValue.ToString(),
- StringComparison.OrdinalIgnoreCase);
+ 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;
}
}
}
diff --git a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
index a5369c441c..cbe82979bc 100644
--- a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
+++ b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
@@ -27,13 +27,18 @@ namespace Jellyfin.Api.Helpers
///
/// Codec name for FLAC.
///
- public const string FLAC = "fLaC";
+ public const string FLAC = "flac";
///
/// Codec name for ALAC.
///
public const string ALAC = "alac";
+ ///
+ /// Codec name for OPUS.
+ ///
+ public const string OPUS = "opus";
+
///
/// Gets a MP3 codec string.
///
@@ -101,6 +106,15 @@ namespace Jellyfin.Api.Helpers
return ALAC;
}
+ ///
+ /// Gets an OPUS codec string.
+ ///
+ /// OPUS codec string.
+ public static string GetOPUSString()
+ {
+ return OPUS;
+ }
+
///
/// Gets a H.264 codec string.
///