From 143f5ba9d585ab9fc8b3753b149a08b01f692bf7 Mon Sep 17 00:00:00 2001 From: Deluan Date: Fri, 20 Aug 2021 21:33:12 -0400 Subject: [PATCH] Import song duration with hundredths when using TagLib This is how ffmpeg extractor currently works, and it makes album durations more precise. --- scanner/metadata/metadata_test.go | 4 ++-- scanner/metadata/taglib/taglib.go | 9 +++++++++ scanner/metadata/taglib/taglib_test.go | 4 ++-- scanner/metadata/taglib/taglib_wrapper.cpp | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/scanner/metadata/metadata_test.go b/scanner/metadata/metadata_test.go index 897be708..d1f077e0 100644 --- a/scanner/metadata/metadata_test.go +++ b/scanner/metadata/metadata_test.go @@ -32,7 +32,7 @@ var _ = Describe("Tags", func() { Expect(n).To(Equal(1)) Expect(t).To(Equal(2)) Expect(m.HasPicture()).To(BeTrue()) - Expect(m.Duration()).To(BeNumerically("~", 1, 0.01)) + Expect(m.Duration()).To(BeNumerically("~", 1.02, 0.01)) Expect(m.BitRate()).To(Equal(192)) Expect(m.FilePath()).To(Equal("tests/fixtures/test.mp3")) Expect(m.Suffix()).To(Equal("mp3")) @@ -42,7 +42,7 @@ var _ = Describe("Tags", func() { Expect(err).To(BeNil()) Expect(m.Title()).To(BeEmpty()) Expect(m.HasPicture()).To(BeFalse()) - Expect(m.Duration()).To(BeNumerically("~", 1.00, 0.01)) + Expect(m.Duration()).To(BeNumerically("~", 1.04, 0.01)) Expect(m.Suffix()).To(Equal("ogg")) Expect(m.FilePath()).To(Equal("tests/fixtures/test.ogg")) Expect(m.Size()).To(Equal(int64(5065))) diff --git a/scanner/metadata/taglib/taglib.go b/scanner/metadata/taglib/taglib.go index e69fb34b..9d22d394 100644 --- a/scanner/metadata/taglib/taglib.go +++ b/scanner/metadata/taglib/taglib.go @@ -1,6 +1,8 @@ package taglib import ( + "strconv" + "github.com/navidrome/navidrome/log" ) @@ -32,6 +34,13 @@ func (e *Parser) extractMetadata(filePath string) (parsedTags, error) { "tracknumber": {"trck", "_track"}, } + if length, ok := tags["lengthinmilliseconds"]; ok && len(length) > 0 { + millis, _ := strconv.Atoi(length[0]) + if duration := float64(millis) / 1000.0; duration > 0 { + tags["duration"] = []string{strconv.FormatFloat(duration, 'f', 2, 32)} + } + } + for tagName, alternatives := range alternativeTags { for _, altName := range alternatives { if altValue, ok := tags[altName]; ok { diff --git a/scanner/metadata/taglib/taglib_test.go b/scanner/metadata/taglib/taglib_test.go index 9f237916..9234c77f 100644 --- a/scanner/metadata/taglib/taglib_test.go +++ b/scanner/metadata/taglib/taglib_test.go @@ -27,7 +27,7 @@ var _ = Describe("Parser", func() { Expect(m).To(HaveKeyWithValue("tracknumber", []string{"2/10", "2/10", "2"})) Expect(m).To(HaveKeyWithValue("discnumber", []string{"1/2"})) Expect(m).To(HaveKeyWithValue("has_picture", []string{"true"})) - Expect(m).To(HaveKeyWithValue("duration", []string{"1"})) + Expect(m).To(HaveKeyWithValue("duration", []string{"1.02"})) Expect(m).To(HaveKeyWithValue("bitrate", []string{"192"})) Expect(m).To(HaveKeyWithValue("comment", []string{"Comment1\nComment2"})) Expect(m).To(HaveKeyWithValue("lyrics", []string{"Lyrics 1\rLyrics 2"})) @@ -37,7 +37,7 @@ var _ = Describe("Parser", func() { Expect(err).To(BeNil()) Expect(m).ToNot(HaveKey("title")) Expect(m).ToNot(HaveKey("has_picture")) - Expect(m).To(HaveKeyWithValue("duration", []string{"1"})) + Expect(m).To(HaveKeyWithValue("duration", []string{"1.04"})) Expect(m).To(HaveKeyWithValue("fbpm", []string{"141.7"})) // TabLib 1.12 returns 18, previous versions return 39. diff --git a/scanner/metadata/taglib/taglib_wrapper.cpp b/scanner/metadata/taglib/taglib_wrapper.cpp index 353587c1..9f77748a 100644 --- a/scanner/metadata/taglib/taglib_wrapper.cpp +++ b/scanner/metadata/taglib/taglib_wrapper.cpp @@ -31,6 +31,7 @@ int taglib_read(const char *filename, unsigned long id) { // Add audio properties to the tags const TagLib::AudioProperties *props(f.audioProperties()); go_map_put_int(id, (char *)"duration", props->length()); + go_map_put_int(id, (char *)"lengthinmilliseconds", props->lengthInMilliseconds()); go_map_put_int(id, (char *)"bitrate", props->bitrate()); TagLib::PropertyMap tags = f.file()->properties();