aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgnattu <gnattuoc@me.com>2024-04-22 21:02:20 +0800
committergnattu <gnattuoc@me.com>2024-07-17 21:27:35 +0800
commit78929418cc3aa783db3abaf99d15ba55e41cc2ac (patch)
tree08516d6f66fe6c10670c68b9b106f8dfe92a5353
parentc050abf3e848a3dc0968b18baaee5d0ffb54b334 (diff)
Use better audio VBR settings
LAME's VBR mode only has advantage over a certain bitrate range. For very low and very high bitrate, use the ABR mode instead. aac_at's CVBR mode produces very good quality and is not worse than its TVBR mode in blind testing. Use this mode for convenience. The ffmpeg native aac encoder will have quality regression with its VBR mode. Always use CBR mode for ffmpeg's native aac encoder. Signed-off-by: gnattu <gnattuoc@me.com>
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs33
2 files changed, 25 insertions, 12 deletions
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index 68602c80d..1e99a9ee3 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -1671,7 +1671,7 @@ public class DynamicHlsController : BaseJellyfinApiController
if (audioBitrate.HasValue && !EncodingHelper.LosslessAudioCodecs.Contains(state.ActualOutputAudioCodec, StringComparison.OrdinalIgnoreCase))
{
- var vbrParam = _encodingHelper.GetAudioVbrModeParam(audioCodec, audioBitrate.Value / (audioChannels ?? 2));
+ var vbrParam = _encodingHelper.GetAudioVbrModeParam(audioCodec, audioBitrate.Value, audioChannels ?? 2);
if (_encodingOptions.EnableAudioVbr && vbrParam is not null)
{
audioTranscodeParams += vbrParam;
@@ -1724,7 +1724,7 @@ public class DynamicHlsController : BaseJellyfinApiController
var bitrate = state.OutputAudioBitrate;
if (bitrate.HasValue && !EncodingHelper.LosslessAudioCodecs.Contains(actualOutputAudioCodec, StringComparison.OrdinalIgnoreCase))
{
- var vbrParam = _encodingHelper.GetAudioVbrModeParam(audioCodec, bitrate.Value / (channels ?? 2));
+ var vbrParam = _encodingHelper.GetAudioVbrModeParam(audioCodec, bitrate.Value, channels ?? 2);
if (_encodingOptions.EnableAudioVbr && vbrParam is not null)
{
args += vbrParam;
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 9d7d2fd12..a122f3d19 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -2586,8 +2586,9 @@ namespace MediaBrowser.Controller.MediaEncoding
return 128000 * (outputAudioChannels ?? audioStream.Channels ?? 2);
}
- public string GetAudioVbrModeParam(string encoder, int bitratePerChannel)
+ public string GetAudioVbrModeParam(string encoder, int bitrate, int channels)
{
+ var bitratePerChannel = bitrate / channels;
if (string.Equals(encoder, "libfdk_aac", StringComparison.OrdinalIgnoreCase))
{
return " -vbr:a " + bitratePerChannel switch
@@ -2602,14 +2603,26 @@ namespace MediaBrowser.Controller.MediaEncoding
if (string.Equals(encoder, "libmp3lame", StringComparison.OrdinalIgnoreCase))
{
- return " -qscale:a " + bitratePerChannel switch
+ // lame's VBR is only good for a certain bitrate range
+ // For very low and very high bitrate, use abr mode
+ if (bitratePerChannel is < 122500 and > 48000)
{
- < 48000 => "8",
- < 64000 => "6",
- < 88000 => "4",
- < 112000 => "2",
- _ => "0"
- };
+ return " -qscale:a " + bitratePerChannel switch
+ {
+ < 64000 => "6",
+ < 88000 => "4",
+ < 112000 => "2",
+ _ => "0"
+ };
+ }
+
+ return " -abr:a 1" + " -b:a " + bitrate;
+ }
+
+ if (string.Equals(encoder, "aac_at", StringComparison.OrdinalIgnoreCase))
+ {
+ // aac_at's CVBR mode
+ return " -aac_at_mode:a 2" + " -b:a " + bitrate;
}
if (string.Equals(encoder, "libvorbis", StringComparison.OrdinalIgnoreCase))
@@ -6962,7 +6975,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var bitrate = state.OutputAudioBitrate;
if (bitrate.HasValue && !LosslessAudioCodecs.Contains(codec, StringComparison.OrdinalIgnoreCase))
{
- var vbrParam = GetAudioVbrModeParam(codec, bitrate.Value / (channels ?? 2));
+ var vbrParam = GetAudioVbrModeParam(codec, bitrate.Value, channels ?? 2);
if (encodingOptions.EnableAudioVbr && vbrParam is not null)
{
args += vbrParam;
@@ -6993,7 +7006,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (bitrate.HasValue && !LosslessAudioCodecs.Contains(outputCodec, StringComparison.OrdinalIgnoreCase))
{
- var vbrParam = GetAudioVbrModeParam(GetAudioEncoder(state), bitrate.Value / (channels ?? 2));
+ var vbrParam = GetAudioVbrModeParam(GetAudioEncoder(state), bitrate.Value, channels ?? 2);
if (encodingOptions.EnableAudioVbr && vbrParam is not null)
{
audioTranscodeParams.Add(vbrParam);