diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index d208879d17..4e45fd24ad 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -81,6 +81,7 @@
- [Maxr1998](https://github.com/Maxr1998)
- [mcarlton00](https://github.com/mcarlton00)
- [mitchfizz05](https://github.com/mitchfizz05)
+ - [mohd-akram](https://github.com/mohd-akram)
- [MrTimscampi](https://github.com/MrTimscampi)
- [n8225](https://github.com/n8225)
- [Nalsai](https://github.com/Nalsai)
diff --git a/Jellyfin.Data/Enums/AudioSpatialFormat.cs b/Jellyfin.Data/Enums/AudioSpatialFormat.cs
new file mode 100644
index 0000000000..5e3a123320
--- /dev/null
+++ b/Jellyfin.Data/Enums/AudioSpatialFormat.cs
@@ -0,0 +1,22 @@
+namespace Jellyfin.Data.Enums;
+
+///
+/// An enum representing formats of spatial audio.
+///
+public enum AudioSpatialFormat
+{
+ ///
+ /// None audio spatial format.
+ ///
+ None,
+
+ ///
+ /// Dolby Atmos audio spatial format.
+ ///
+ DolbyAtmos,
+
+ ///
+ /// DTS:X audio spatial format.
+ ///
+ DTSX,
+}
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index 34642b83aa..ae4a008bb3 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
@@ -214,6 +215,27 @@ namespace MediaBrowser.Model.Entities
}
}
+ ///
+ /// Gets the audio spatial format.
+ ///
+ /// The audio spatial format.
+ [DefaultValue(AudioSpatialFormat.None)]
+ public AudioSpatialFormat AudioSpatialFormat
+ {
+ get
+ {
+ if (Type != MediaStreamType.Audio || string.IsNullOrEmpty(Profile))
+ {
+ return AudioSpatialFormat.None;
+ }
+
+ return
+ Profile.Contains("Dolby Atmos", StringComparison.OrdinalIgnoreCase) ? AudioSpatialFormat.DolbyAtmos :
+ Profile.Contains("DTS:X", StringComparison.OrdinalIgnoreCase) ? AudioSpatialFormat.DTSX :
+ AudioSpatialFormat.None;
+ }
+ }
+
public string LocalizedUndefined { get; set; }
public string LocalizedDefault { get; set; }
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 198dc63efe..344ac8971c 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -46,7 +46,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
var internalMediaInfoResult = JsonSerializer.Deserialize(bytes, _jsonOptions);
MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/video_metadata.mkv", MediaProtocol.File);
- Assert.Single(res.MediaStreams);
+ Assert.Equal(3, res.MediaStreams.Count);
Assert.NotNull(res.VideoStream);
Assert.Equal("4:3", res.VideoStream.AspectRatio);
@@ -83,6 +83,14 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.Equal(1, res.VideoStream.BlPresentFlag);
Assert.Equal(0, res.VideoStream.DvBlSignalCompatibilityId);
+ var audio1 = res.MediaStreams[1];
+ Assert.Equal("eac3", audio1.Codec);
+ Assert.Equal(AudioSpatialFormat.DolbyAtmos, audio1.AudioSpatialFormat);
+
+ var audio2 = res.MediaStreams[2];
+ Assert.Equal("dts", audio2.Codec);
+ Assert.Equal(AudioSpatialFormat.DTSX, audio2.AudioSpatialFormat);
+
Assert.Empty(res.Chapters);
Assert.Equal("Just color bars", res.Overview);
}
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
index 519d81179c..a49c686900 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
+++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
@@ -61,6 +61,92 @@
"dv_bl_signal_compatibility_id": 0
}
]
+ },
+ {
+ "index": 1,
+ "codec_name": "eac3",
+ "codec_long_name": "ATSC A/52B (AC-3, E-AC-3)",
+ "profile": "Dolby Digital Plus + Dolby Atmos",
+ "codec_type": "audio",
+ "codec_tag_string": "[0][0][0][0]",
+ "codec_tag": "0x0000",
+ "sample_fmt": "fltp",
+ "sample_rate": "48000",
+ "channels": 6,
+ "channel_layout": "5.1(side)",
+ "bits_per_sample": 0,
+ "initial_padding": 0,
+ "r_frame_rate": "0/0",
+ "avg_frame_rate": "0/0",
+ "time_base": "1/1000",
+ "start_pts": 0,
+ "start_time": "0.000000",
+ "bit_rate": "640000",
+ "disposition": {
+ "default": 1,
+ "dub": 0,
+ "original": 1,
+ "comment": 0,
+ "lyrics": 0,
+ "karaoke": 0,
+ "forced": 0,
+ "hearing_impaired": 0,
+ "visual_impaired": 0,
+ "clean_effects": 0,
+ "attached_pic": 0,
+ "timed_thumbnails": 0,
+ "captions": 0,
+ "descriptions": 0,
+ "metadata": 0,
+ "dependent": 0,
+ "still_image": 0
+ },
+ "tags": {
+ "language": "eng"
+ }
+ },
+ {
+ "index": 2,
+ "codec_name": "dts",
+ "codec_long_name": "DCA (DTS Coherent Acoustics)",
+ "profile": "DTS-HD MA + DTS:X",
+ "codec_type": "audio",
+ "codec_tag_string": "[0][0][0][0]",
+ "codec_tag": "0x0000",
+ "sample_fmt": "s32p",
+ "sample_rate": "48000",
+ "channels": 8,
+ "channel_layout": "7.1",
+ "bits_per_sample": 0,
+ "initial_padding": 0,
+ "r_frame_rate": "0/0",
+ "avg_frame_rate": "0/0",
+ "time_base": "1/1000",
+ "start_pts": 0,
+ "start_time": "0.000000",
+ "bits_per_raw_sample": "24",
+ "disposition": {
+ "default": 0,
+ "dub": 0,
+ "original": 0,
+ "comment": 0,
+ "lyrics": 0,
+ "karaoke": 0,
+ "forced": 0,
+ "hearing_impaired": 0,
+ "visual_impaired": 0,
+ "clean_effects": 0,
+ "attached_pic": 0,
+ "timed_thumbnails": 0,
+ "captions": 0,
+ "descriptions": 0,
+ "metadata": 0,
+ "dependent": 0,
+ "still_image": 0
+ },
+ "tags": {
+ "language": "eng"
+ }
}
],
"chapters": [
@@ -68,7 +154,7 @@
],
"format": {
"filename": "some_metadata.mkv",
- "nb_streams": 1,
+ "nb_streams": 3,
"nb_programs": 0,
"format_name": "matroska,webm",
"format_long_name": "Matroska / WebM",