Fixed: Some bugs in new metadata writing (#677)

* Fixed: Don't fail reading m4a files when no 'day' tag set

* Fixed: Make sure Quality and MediaInfo are set if tag reading failed

* Add more tests for AudioTagService
pull/685/head
ta264 6 years ago committed by GitHub
parent 24737baee6
commit d552770da9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,6 +11,7 @@ using System.Collections;
using System.Linq; using System.Linq;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
{ {
@ -141,7 +142,11 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
{ {
var val1 = (IEnumerable) property.GetValue(a, null); var val1 = (IEnumerable) property.GetValue(a, null);
var val2 = (IEnumerable) property.GetValue(b, null); var val2 = (IEnumerable) property.GetValue(b, null);
val1.Should().BeEquivalentTo(val2, $"{property.Name} should be equal");
if (val1 != null || val2 != null)
{
val1.Should().BeEquivalentTo(val2, $"{property.Name} should be equal");
}
} }
} }
} }
@ -208,5 +213,71 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
tag.MusicBrainzAlbumComment.Should().BeNull(); tag.MusicBrainzAlbumComment.Should().BeNull();
tag.MusicBrainzReleaseTrackId.Should().BeNull(); tag.MusicBrainzReleaseTrackId.Should().BeNull();
} }
[Test, TestCaseSource(typeof(TestCaseFactory), "TestCases")]
public void should_read_audiotag_from_file_with_no_tags(string filename, string[] skipProperties)
{
GivenFileCopy(filename);
var path = copiedFile;
Subject.RemoveAllTags(path);
var tag = Subject.ReadAudioTag(path);
var expected = new AudioTag() {
Performers = new string[0],
AlbumArtists = new string[0]
};
VerifySame(tag, expected, skipProperties);
tag.Quality.Should().NotBeNull();
tag.MediaInfo.Should().NotBeNull();
}
[Test, TestCaseSource(typeof(TestCaseFactory), "TestCases")]
public void should_read_parsedtrackinfo_from_file_with_no_tags(string filename, string[] skipProperties)
{
GivenFileCopy(filename);
var path = copiedFile;
Subject.RemoveAllTags(path);
var tag = Subject.ReadTags(path);
tag.Quality.Should().NotBeNull();
tag.MediaInfo.Should().NotBeNull();
}
[Test, TestCaseSource(typeof(TestCaseFactory), "TestCases")]
public void should_set_quality_and_mediainfo_for_corrupt_file(string filename, string[] skipProperties)
{
// use missing to simulate corrupt
var tag = Subject.ReadAudioTag(filename.Replace("nin", "missing"));
var expected = new AudioTag();
VerifySame(tag, expected, skipProperties);
tag.Quality.Should().NotBeNull();
tag.MediaInfo.Should().NotBeNull();
ExceptionVerification.ExpectedErrors(1);
}
[Test, TestCaseSource(typeof(TestCaseFactory), "TestCases")]
public void should_read_file_with_only_title_tag(string filename, string[] ignored)
{
GivenFileCopy(filename);
var path = copiedFile;
Subject.RemoveAllTags(path);
var nametag = new AudioTag();
nametag.Title = "test";
nametag.Write(path);
var tag = Subject.ReadTags(path);
tag.Title.Should().Be("test");
tag.Quality.Should().NotBeNull();
tag.MediaInfo.Should().NotBeNull();
}
} }
} }

@ -150,7 +150,7 @@ namespace NzbDrone.Core.MediaFiles
{ {
var appletag = (TagLib.Mpeg4.AppleTag) file.GetTag(TagTypes.Apple); var appletag = (TagLib.Mpeg4.AppleTag) file.GetTag(TagTypes.Apple);
Media = appletag.GetDashBox("com.apple.iTunes", "MEDIA"); Media = appletag.GetDashBox("com.apple.iTunes", "MEDIA");
Date = DateTime.TryParse(appletag.DataBoxes(FixAppleId("day")).First().Text, out tempDate) ? tempDate : default(DateTime?); Date = DateTime.TryParse(appletag.DataBoxes(FixAppleId("day")).FirstOrDefault()?.Text, out tempDate) ? tempDate : default(DateTime?);
OriginalReleaseDate = DateTime.TryParse(appletag.GetDashBox("com.apple.iTunes", "Original Date"), out tempDate) ? tempDate : default(DateTime?); OriginalReleaseDate = DateTime.TryParse(appletag.GetDashBox("com.apple.iTunes", "Original Date"), out tempDate) ? tempDate : default(DateTime?);
MusicBrainzAlbumComment = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Album Comment"); MusicBrainzAlbumComment = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Album Comment");
MusicBrainzReleaseTrackId = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Release Track Id"); MusicBrainzReleaseTrackId = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Release Track Id");
@ -168,11 +168,7 @@ namespace NzbDrone.Core.MediaFiles
if (bitrate == 0) if (bitrate == 0)
{ {
// Taglib can't read bitrate for Opus. // Taglib can't read bitrate for Opus.
// Taglib File.Length is unreliable so use System.IO bitrate = EstimateBitrate(file, path);
var size = new System.IO.FileInfo(path).Length;
var duration = file.Properties.Duration.TotalSeconds;
bitrate = (int) ((size * 8L) / (duration * 1024));
Logger.Trace($"Estimating bitrate. Size: {size} Duration: {duration} Bitrate: {bitrate}");
} }
Logger.Debug("Audio Properties: " + acodec.Description + ", Bitrate: " + bitrate + ", Sample Size: " + Logger.Debug("Audio Properties: " + acodec.Description + ", Bitrate: " + bitrate + ", Sample Size: " +
@ -193,17 +189,22 @@ namespace NzbDrone.Core.MediaFiles
IsValid = true; IsValid = true;
} }
catch (CorruptFileException ex)
{
Logger.Warn(ex, $"Tag reading failed for {path}. File is corrupt");
}
catch (Exception ex) catch (Exception ex)
{ {
Logger.Warn() if (ex is CorruptFileException)
.Exception(ex) {
.Message($"Tag reading failed for {path}") Logger.Warn(ex, $"Tag reading failed for {path}. File is corrupt");
.WriteSentryWarn("Tag reading failed") }
.Write(); else
{
// Log as error so it goes to sentry with correct fingerprint
Logger.Error(ex, "Tag reading failed for {0}", path);
}
// make sure these are initialized to avoid errors later on
Quality = QualityParser.ParseQuality(path, null, EstimateBitrate(file, path));
Logger.Debug($"Quality parsed: {Quality}, Source: {Quality.QualityDetectionSource}");
MediaInfo = new MediaInfoModel();
} }
finally finally
{ {
@ -211,6 +212,25 @@ namespace NzbDrone.Core.MediaFiles
} }
} }
private int EstimateBitrate(TagLib.File file, string path)
{
int bitrate = 0;
try
{
// Taglib File.Length is unreliable so use System.IO
var size = new System.IO.FileInfo(path).Length;
var duration = file.Properties.Duration.TotalSeconds;
bitrate = (int) ((size * 8L) / (duration * 1024));
Logger.Trace($"Estimating bitrate. Size: {size} Duration: {duration} Bitrate: {bitrate}");
}
catch
{
}
return bitrate;
}
private DateTime? ReadId3Date(TagLib.Id3v2.Tag tag, string dateTag) private DateTime? ReadId3Date(TagLib.Id3v2.Tag tag, string dateTag)
{ {
string date = tag.GetTextAsString(dateTag); string date = tag.GetTextAsString(dateTag);
@ -301,6 +321,11 @@ namespace NzbDrone.Core.MediaFiles
{ {
Logger.Debug($"Starting tag write for {path}"); Logger.Debug($"Starting tag write for {path}");
// patch up any null fields to work around TagLib exception for
// WMA with null performers/albumartists
Performers = Performers ?? new string[0];
AlbumArtists = AlbumArtists ?? new string[0];
TagLib.File file = null; TagLib.File file = null;
try try
{ {
@ -544,7 +569,11 @@ namespace NzbDrone.Core.MediaFiles
{ {
if (!tag.IsValid) if (!tag.IsValid)
{ {
return new ParsedTrackInfo { Language = Language.English }; return new ParsedTrackInfo {
Language = Language.English,
Quality = tag.Quality ?? new QualityModel { Quality = NzbDrone.Core.Qualities.Quality.Unknown },
MediaInfo = tag.MediaInfo ?? new MediaInfoModel()
};
} }
var artist = tag.AlbumArtists?.FirstOrDefault(); var artist = tag.AlbumArtists?.FirstOrDefault();

Loading…
Cancel
Save