Use source audio bitrate if requested codec is lossless

This commit is contained in:
Shadowghost 2023-03-02 20:57:59 +01:00
parent 31712e5da9
commit 3d735e242a
4 changed files with 60 additions and 42 deletions

View File

@ -13,6 +13,7 @@ using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Extensions;
using Jellyfin.MediaEncoding.Hls.Playlist; using Jellyfin.MediaEncoding.Hls.Playlist;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
@ -1694,7 +1695,7 @@ namespace Jellyfin.Api.Controllers
audioTranscodeParams += "-acodec " + audioCodec; audioTranscodeParams += "-acodec " + audioCodec;
if (state.OutputAudioBitrate.HasValue) if (state.OutputAudioBitrate.HasValue && !EncodingHelper.LosslessAudioCodecs.Contains(state.ActualOutputAudioCodec, StringComparison.OrdinalIgnoreCase))
{ {
audioTranscodeParams += " -ab " + state.OutputAudioBitrate.Value.ToString(CultureInfo.InvariantCulture); audioTranscodeParams += " -ab " + state.OutputAudioBitrate.Value.ToString(CultureInfo.InvariantCulture);
} }
@ -1715,11 +1716,11 @@ namespace Jellyfin.Api.Controllers
// dts, flac, opus and truehd are experimental in mp4 muxer // dts, flac, opus and truehd are experimental in mp4 muxer
var strictArgs = string.Empty; var strictArgs = string.Empty;
var actualOutputAudioCodec = state.ActualOutputAudioCodec;
if (string.Equals(state.ActualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase) if (string.Equals(actualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase)
|| string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase) || string.Equals(actualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|| string.Equals(state.ActualOutputAudioCodec, "dts", StringComparison.OrdinalIgnoreCase) || string.Equals(actualOutputAudioCodec, "dts", StringComparison.OrdinalIgnoreCase)
|| string.Equals(state.ActualOutputAudioCodec, "truehd", StringComparison.OrdinalIgnoreCase)) || string.Equals(actualOutputAudioCodec, "truehd", StringComparison.OrdinalIgnoreCase))
{ {
strictArgs = " -strict -2"; strictArgs = " -strict -2";
} }
@ -1748,8 +1749,7 @@ namespace Jellyfin.Api.Controllers
} }
var bitrate = state.OutputAudioBitrate; var bitrate = state.OutputAudioBitrate;
if (bitrate.HasValue && !EncodingHelper.LosslessAudioCodecs.Contains(actualOutputAudioCodec, StringComparison.OrdinalIgnoreCase))
if (bitrate.HasValue)
{ {
args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture); args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
} }

View File

@ -8,6 +8,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -220,11 +221,26 @@ namespace Jellyfin.Api.Helpers
var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main"); var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main");
sdrVideoUrl += "&AllowVideoStreamCopy=false"; sdrVideoUrl += "&AllowVideoStreamCopy=false";
var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec); var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream, state.OutputAudioChannels) ?? 0; var sdrOutputAudioBitrate = 0;
var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate; 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;
}
AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); 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 // Restore the video codec
state.OutputVideoCodec = "copy"; state.OutputVideoCodec = "copy";

View File

@ -182,12 +182,18 @@ namespace Jellyfin.Api.Helpers
: GetOutputFileExtension(state, mediaSource); : GetOutputFileExtension(state, mediaSource);
} }
var outputAudioCodec = streamingRequest.AudioCodec;
if (EncodingHelper.LosslessAudioCodecs.Contains(outputAudioCodec))
{
state.OutputAudioBitrate = state.AudioStream.BitRate ?? 0;
}
else
{
state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(streamingRequest.AudioBitRate, streamingRequest.AudioCodec, state.AudioStream, state.OutputAudioChannels) ?? 0;
}
state.OutputAudioCodec = outputAudioCodec;
state.OutputContainer = (containerInternal ?? string.Empty).TrimStart('.'); state.OutputContainer = (containerInternal ?? string.Empty).TrimStart('.');
state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(streamingRequest.AudioBitRate, streamingRequest.AudioCodec, state.AudioStream, state.OutputAudioChannels);
state.OutputAudioCodec = streamingRequest.AudioCodec;
state.OutputAudioChannels = encodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec); state.OutputAudioChannels = encodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec);
if (state.VideoRequest != null) if (state.VideoRequest != null)

View File

@ -62,6 +62,16 @@ namespace MediaBrowser.Controller.MediaEncoding
"Main10" "Main10"
}; };
public static readonly string[] LosslessAudioCodecs = new string[]
{
"alac",
"ape",
"flac",
"mlp",
"truehd",
"wavpack"
};
public EncodingHelper( public EncodingHelper(
IApplicationPaths appPaths, IApplicationPaths appPaths,
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder,
@ -2104,17 +2114,6 @@ namespace MediaBrowser.Controller.MediaEncoding
}; };
} }
if (string.Equals(audioCodec, "flac", StringComparison.OrdinalIgnoreCase)
|| string.Equals(audioCodec, "alac", StringComparison.OrdinalIgnoreCase))
{
if (inputChannels >= 6)
{
return Math.Min(3584000, bitrate);
}
return Math.Min(1536000, bitrate);
}
if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase) if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase)
|| string.Equals(audioCodec, "dca", StringComparison.OrdinalIgnoreCase)) || string.Equals(audioCodec, "dca", StringComparison.OrdinalIgnoreCase))
{ {
@ -2127,20 +2126,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}; };
} }
if (string.Equals(audioCodec, "truehd", StringComparison.OrdinalIgnoreCase))
{
return (inputChannels, outputChannels) switch
{
(> 0, > 0) => Math.Min(outputChannels * 768000, bitrate),
(> 0, _) => Math.Min(inputChannels * 768000, bitrate),
(_, _) => Math.Min(768000, bitrate)
};
}
// Empty bitrate area is not allow on iOS // Empty bitrate area is not allow on iOS
// Default audio bitrate to 128K per channel if we don't have codec specific defaults // Default audio bitrate to 128K per channel if we don't have codec specific defaults
// https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options // https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options
return 128000 * (outputAudioChannels ?? audioStream.Channels ?? 1); return 128000 * (outputAudioChannels ?? audioStream.Channels ?? 2);
} }
public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions) public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions)
@ -5562,7 +5551,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var bitrate = state.OutputAudioBitrate; var bitrate = state.OutputAudioBitrate;
if (bitrate.HasValue) if (bitrate.HasValue && !LosslessAudioCodecs.Contains(codec, StringComparison.OrdinalIgnoreCase))
{ {
args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture); args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
} }
@ -5582,8 +5571,10 @@ namespace MediaBrowser.Controller.MediaEncoding
var audioTranscodeParams = new List<string>(); var audioTranscodeParams = new List<string>();
var bitrate = state.OutputAudioBitrate; var bitrate = state.OutputAudioBitrate;
var channels = state.OutputAudioChannels;
var outputCodec = state.OutputAudioCodec;
if (bitrate.HasValue) if (bitrate.HasValue && !LosslessAudioCodecs.Contains(outputCodec, StringComparison.OrdinalIgnoreCase))
{ {
audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture)); audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture));
} }
@ -5593,7 +5584,12 @@ namespace MediaBrowser.Controller.MediaEncoding
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture)); audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture));
} }
if (!string.Equals(state.OutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)) if (!string.IsNullOrEmpty(outputCodec))
{
audioTranscodeParams.Add("-acodec " + GetAudioEncoder(state));
}
if (!string.Equals(outputCodec, "opus", StringComparison.OrdinalIgnoreCase))
{ {
// opus only supports specific sampling rates // opus only supports specific sampling rates
var sampleRate = state.OutputAudioSampleRate; var sampleRate = state.OutputAudioSampleRate;