diff --git a/frontend/src/Episode/Summary/MediaInfo.tsx b/frontend/src/Episode/Summary/MediaInfo.tsx index d9c80db69..72abcdb02 100644 --- a/frontend/src/Episode/Summary/MediaInfo.tsx +++ b/frontend/src/Episode/Summary/MediaInfo.tsx @@ -23,7 +23,10 @@ function MediaInfo(props: MediaInfoProps) { if (key === 'audioStreams') { return value.map((audioStream, index) => { - const language = getLanguageName(audioStream.language); + const language = + audioStream.language === 'und' + ? translate('Unknown') + : getLanguageName(audioStream.language); let line = `${language}`; diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/225_mediainfo_multiple_streamsFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/225_mediainfo_multiple_streamsFixture.cs index 180144d62..bf528e938 100644 --- a/src/NzbDrone.Core.Test/Datastore/Migration/225_mediainfo_multiple_streamsFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/Migration/225_mediainfo_multiple_streamsFixture.cs @@ -97,6 +97,63 @@ public void should_convert_non_empty_media_info() mediainfo.SubtitleStreams.Select(s => s.Language).Should().BeEquivalentTo("eng", "ger", "rum"); } + [Test] + public void should_convert_non_empty_media_info_with_empty_audio_languages() + { + var db = WithMigrationTestDb(c => + { + c.Insert.IntoTable("EpisodeFiles").Row(new + { + SeriesId = 1, + SeasonNumber = 1, + RelativePath = "Season 01/S01E05.mkv", + Size = 125.Megabytes(), + DateAdded = DateTime.UtcNow, + OriginalFilePath = "Series.Title.S01E05.720p.HDTV.x265-Sonarr.mkv", + ReleaseGroup = "Sonarr", + Quality = new QualityModel(Quality.HDTV720p).ToJson(), + Languages = "[1]", + MediaInfo = new + { + AudioFormat = "truehd", + AudioCodecID = "[0][0][0][0]", + AudioProfile = "Dolby TrueHD + Dolby Atmos", + AudioBitrate = 224000, + AudioChannels = 2, + AudioChannelPositions = "stereo", + AudioLanguages = new List(), + Subtitles = new List { "ger", "eng", "rum" }, + ScanType = "Progressive", + SchemaRevision = 13 + }.ToJson() + }); + }); + + var items = db.Query("SELECT \"Id\", \"RelativePath\", \"MediaInfo\" FROM \"EpisodeFiles\""); + + items.Should().HaveCount(1); + + var mediainfo = items.First().MediaInfo; + + mediainfo.AudioFormat.Should().BeNull(); + mediainfo.AudioCodecID.Should().BeNull(); + mediainfo.AudioProfile.Should().BeNull(); + mediainfo.AudioBitrate.Should().BeNull(); + mediainfo.AudioChannels.Should().BeNull(); + mediainfo.AudioChannelPositions.Should().BeNull(); + + mediainfo.AudioStreams.First().Format.Should().Be("truehd"); + mediainfo.AudioStreams.First().CodecId.Should().Be("[0][0][0][0]"); + mediainfo.AudioStreams.First().Profile.Should().Be("Dolby TrueHD + Dolby Atmos"); + mediainfo.AudioStreams.First().Bitrate.Should().Be(224000); + mediainfo.AudioStreams.First().Channels.Should().Be(2); + mediainfo.AudioStreams.First().ChannelPositions.Should().Be("stereo"); + mediainfo.AudioStreams.First().Language.Should().Be("und"); + + mediainfo.AudioStreams.Select(s => s.Language).Should().BeEquivalentTo("und"); + mediainfo.SubtitleStreams.Select(s => s.Language).Should().BeEquivalentTo("eng", "ger", "rum"); + } + [Test] public void should_convert_to_null_on_invalid_media_info() { diff --git a/src/NzbDrone.Core/Datastore/Migration/225_mediainfo_multiple_streams.cs b/src/NzbDrone.Core/Datastore/Migration/225_mediainfo_multiple_streams.cs index f743a88c0..b16117241 100644 --- a/src/NzbDrone.Core/Datastore/Migration/225_mediainfo_multiple_streams.cs +++ b/src/NzbDrone.Core/Datastore/Migration/225_mediainfo_multiple_streams.cs @@ -126,13 +126,19 @@ private static List MigrateAudioStreams(MediaInfo224 ol { Language = language, }) - .ToList(); - audioStreams?.FirstOrDefault()?.Format = old.AudioFormat; - audioStreams?.FirstOrDefault()?.CodecId = old.AudioCodecID; - audioStreams?.FirstOrDefault()?.Profile = old.AudioProfile; - audioStreams?.FirstOrDefault()?.Bitrate = old.AudioBitrate; - audioStreams?.FirstOrDefault()?.Channels = old.AudioChannels; - audioStreams?.FirstOrDefault()?.ChannelPositions = old.AudioChannelPositions; + .ToList() ?? []; + + if (audioStreams.Count == 0) + { + audioStreams.Add(new MediaInfoAudioStream225 { Language = "und" }); + } + + audioStreams.FirstOrDefault()?.Format = old.AudioFormat; + audioStreams.FirstOrDefault()?.CodecId = old.AudioCodecID; + audioStreams.FirstOrDefault()?.Profile = old.AudioProfile; + audioStreams.FirstOrDefault()?.Bitrate = old.AudioBitrate; + audioStreams.FirstOrDefault()?.Channels = old.AudioChannels; + audioStreams.FirstOrDefault()?.ChannelPositions = old.AudioChannelPositions; return audioStreams; } @@ -144,7 +150,7 @@ private static List MigrateSubtitleStreams(MediaInfo { Language = language, }) - .ToList(); + .ToList() ?? []; return subtitleStreams; } diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs index 66dde9cc1..277633ec5 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs @@ -31,7 +31,7 @@ public static decimal FormatAudioChannels(MediaInfoAudioStreamModel audioStream) public static string FormatAudioCodec(MediaInfoAudioStreamModel audioStream, string sceneName) { - if (audioStream.Format == null) + if (audioStream?.Format == null) { return null; } @@ -155,7 +155,7 @@ public static string FormatAudioCodec(MediaInfoAudioStreamModel audioStream, str public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName) { - if (mediaInfo.VideoFormat == null) + if (mediaInfo?.VideoFormat == null) { return null; } @@ -270,7 +270,7 @@ public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName private static decimal? FormatAudioChannelsFromAudioChannelPositions(MediaInfoAudioStreamModel audioStream) { - if (audioStream.ChannelPositions == null) + if (audioStream?.ChannelPositions == null) { return 0; } diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs index 073b510ce..32742bc96 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs @@ -85,13 +85,12 @@ public MediaInfoModel GetMediaInfo(string filename) mediaInfoModel.RawStreamData = string.Concat(analysis.OutputData); mediaInfoModel.AudioStreams = analysis.AudioStreams? - .Where(stream => stream.Language.IsNotNullOrWhiteSpace()) .OrderBy(stream => stream.Index) .Select(stream => { var model = new MediaInfoAudioStreamModel { - Language = stream.Language, + Language = stream.Language.IsNotNullOrWhiteSpace() ? stream.Language : "und", Format = stream.CodecName, CodecId = stream.CodecTagString, Profile = stream.Profile,