diff options
| author | danne <danne.e85@gmail.com> | 2026-06-13 22:44:44 +0200 |
|---|---|---|
| committer | danne <danne.e85@gmail.com> | 2026-06-21 09:43:31 +0200 |
| commit | e4383493a96da86c99516bfdf69ecd609c2dfec2 (patch) | |
| tree | 658cb37e8d60d34f1e04d21f3973f6f6cd809d1f | |
| parent | 3741d7196506cb5061116447c7a7f930587e5c7c (diff) | |
Fix audio sample rate forced to 48 kHz for non-Opus codecs
GetProgressiveAudioFullCommandLine applied the libopus-only sample rate
quantization to every codec except Opus, inverting the intended guard.
A requested rate such as 44100 Hz was therefore snapped to 48000 Hz for
AAC/MP3/FLAC, while Opus (which actually requires the quantization) was
skipped entirely.
Apply the quantization only when the output codec is Opus, and pass the
requested sample rate through unchanged for all other codecs.
Fixes #17026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 15 | ||||
| -rw-r--r-- | tests/Jellyfin.Controller.Tests/MediaEncoding/EncodingHelperTests.cs | 45 |
2 files changed, 53 insertions, 7 deletions
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 650eaa404e..847f4cf187 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -7870,13 +7870,14 @@ namespace MediaBrowser.Controller.MediaEncoding audioTranscodeParams.Add("-ar " + state.BaseRequest.AudioBitRate); } - if (!string.Equals(outputCodec, "opus", StringComparison.OrdinalIgnoreCase)) + var sampleRate = state.OutputAudioSampleRate; + if (sampleRate.HasValue) { - // opus only supports specific sampling rates - var sampleRate = state.OutputAudioSampleRate; - if (sampleRate.HasValue) + var sampleRateValue = sampleRate.Value; + if (string.Equals(outputCodec, "opus", StringComparison.OrdinalIgnoreCase)) { - var sampleRateValue = sampleRate.Value switch + // opus only supports specific sampling rates + sampleRateValue = sampleRate.Value switch { <= 8000 => 8000, <= 12000 => 12000, @@ -7884,9 +7885,9 @@ namespace MediaBrowser.Controller.MediaEncoding <= 24000 => 24000, _ => 48000 }; - - audioTranscodeParams.Add("-ar " + sampleRateValue.ToString(CultureInfo.InvariantCulture)); } + + audioTranscodeParams.Add("-ar " + sampleRateValue.ToString(CultureInfo.InvariantCulture)); } // Copy the movflags from GetProgressiveVideoFullCommandLine diff --git a/tests/Jellyfin.Controller.Tests/MediaEncoding/EncodingHelperTests.cs b/tests/Jellyfin.Controller.Tests/MediaEncoding/EncodingHelperTests.cs index d7ae6a8a18..71b6551d0f 100644 --- a/tests/Jellyfin.Controller.Tests/MediaEncoding/EncodingHelperTests.cs +++ b/tests/Jellyfin.Controller.Tests/MediaEncoding/EncodingHelperTests.cs @@ -11,6 +11,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; using Moq; using Xunit; @@ -203,6 +204,50 @@ public class EncodingHelperTests } } + [Theory] + [InlineData("aac", 44100, 44100)] // non-opus: requested rate must be preserved (issue #17026) + [InlineData("aac", 48000, 48000)] + [InlineData("mp3", 22050, 22050)] + [InlineData("flac", 96000, 96000)] + [InlineData("opus", 44100, 48000)] // opus: must snap to a libopus-supported rate + [InlineData("opus", 22050, 24000)] + [InlineData("opus", 8000, 8000)] + public void GetProgressiveAudioFullCommandLine_SampleRate_OnlyClampedForOpus( + string audioCodec, + int requestedSampleRate, + int expectedSampleRate) + { + var state = BuildAudioState(audioCodec, requestedSampleRate); + var args = CreateHelper().GetProgressiveAudioFullCommandLine(state, new EncodingOptions(), "/tmp/out"); + + Assert.Contains("-ar " + expectedSampleRate, args, StringComparison.Ordinal); + } + + private static EncodingJobInfo BuildAudioState(string audioCodec, int requestedSampleRate) + { + var audio = new MediaStream { Index = 0, Type = MediaStreamType.Audio, Codec = "flac", SampleRate = 96000 }; + + return new EncodingJobInfo(TranscodingJobType.Progressive) + { + MediaSource = new MediaSourceInfo + { + Container = "flac", + MediaStreams = new List<MediaStream> { audio }, + Path = "/media/track.flac", + Protocol = MediaProtocol.File, + }, + AudioStream = audio, + OutputAudioCodec = audioCodec, + BaseRequest = new VideoRequestDto + { + AudioCodec = audioCodec, + AudioSampleRate = requestedSampleRate, + }, + IsVideoRequest = false, + IsInputVideo = false, + }; + } + private static EncodingJobInfo BuildState( MediaStream? subtitle, SubtitleDeliveryMethod? deliveryMethod, |
