diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index dbe5322897..127bdd380d 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -863,7 +863,7 @@ namespace MediaBrowser.MediaEncoding.Probing
{
stream.IsAnamorphic = false;
}
- else if (string.Equals(streamInfo.SampleAspectRatio, "1:1", StringComparison.Ordinal))
+ else if (IsNearSquarePixelSar(streamInfo.SampleAspectRatio))
{
stream.IsAnamorphic = false;
}
@@ -1154,6 +1154,34 @@ namespace MediaBrowser.MediaEncoding.Probing
return Math.Abs(d1 - d2) <= variance;
}
+ ///
+ /// Determines whether a sample aspect ratio represents square (or near-square) pixels.
+ /// Some encoders produce SARs like 3201:3200 for content that is effectively 1:1,
+ /// which would be falsely classified as anamorphic by an exact string comparison.
+ /// A 1% tolerance safely covers encoder rounding artifacts while preserving detection
+ /// of genuine anamorphic content (closest standard is PAL 4:3 at 16:15 = 6.67% off).
+ ///
+ /// The sample aspect ratio string in "N:D" format.
+ /// true if the SAR is within 1% of 1:1; otherwise false.
+ internal static bool IsNearSquarePixelSar(string sar)
+ {
+ if (string.IsNullOrEmpty(sar))
+ {
+ return false;
+ }
+
+ var parts = sar.Split(':');
+ if (parts.Length == 2
+ && double.TryParse(parts[0], CultureInfo.InvariantCulture, out var num)
+ && double.TryParse(parts[1], CultureInfo.InvariantCulture, out var den)
+ && den > 0)
+ {
+ return IsClose(num / den, 1.0, 0.01);
+ }
+
+ return string.Equals(sar, "1:1", StringComparison.Ordinal);
+ }
+
///
/// Gets a frame rate from a string value in ffprobe output
/// This could be a number or in the format of 2997/125.
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 8a2f84734e..8ebbd029ac 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -39,6 +39,23 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
public void GetFrameRate_Success(string value, float? expected)
=> Assert.Equal(expected, ProbeResultNormalizer.GetFrameRate(value));
+ [Theory]
+ [InlineData("1:1", true)]
+ [InlineData("3201:3200", true)]
+ [InlineData("1215:1216", true)]
+ [InlineData("1001:1000", true)]
+ [InlineData("16:15", false)]
+ [InlineData("8:9", false)]
+ [InlineData("32:27", false)]
+ [InlineData("10:11", false)]
+ [InlineData("64:45", false)]
+ [InlineData("4:3", false)]
+ [InlineData("0:1", false)]
+ [InlineData("", false)]
+ [InlineData(null, false)]
+ public void IsNearSquarePixelSar_DetectsCorrectly(string? sar, bool expected)
+ => Assert.Equal(expected, ProbeResultNormalizer.IsNearSquarePixelSar(sar));
+
[Fact]
public void GetMediaInfo_MetaData_Success()
{
@@ -123,6 +140,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.Equal(358, res.VideoStream.Height);
Assert.Equal(720, res.VideoStream.Width);
Assert.Equal("2.40:1", res.VideoStream.AspectRatio);
+ Assert.True(res.VideoStream.IsAnamorphic); // SAR 32:27 — genuinely anamorphic NTSC DVD 16:9
Assert.Equal("yuv420p", res.VideoStream.PixelFormat);
Assert.Equal(31d, res.VideoStream.Level);
Assert.Equal(1, res.VideoStream.RefFrames);