diff --git a/scanner/metadata/ffmpeg.go b/scanner/metadata/ffmpeg.go index 8a4f76f86..c34925de8 100644 --- a/scanner/metadata/ffmpeg.go +++ b/scanner/metadata/ffmpeg.go @@ -26,7 +26,7 @@ func (m *ffmpegMetadata) DiscNumber() (int, int) { return m.parseTuple("tpa", "d type ffmpegExtractor struct{} func (e *ffmpegExtractor) Extract(files ...string) (map[string]Metadata, error) { - args := createProbeCommand(files) + args := e.createProbeCommand(files) log.Trace("Executing command", "args", args) cmd := exec.Command(args[0], args[1:]...) // #nosec @@ -35,9 +35,9 @@ func (e *ffmpegExtractor) Extract(files ...string) (map[string]Metadata, error) if len(output) == 0 { return mds, errors.New("error extracting metadata files") } - infos := parseOutput(string(output)) + infos := e.parseOutput(string(output)) for file, info := range infos { - md, err := extractMetadata(file, info) + md, err := e.extractMetadata(file, info) // Skip files with errors if err == nil { mds[file] = md @@ -63,7 +63,7 @@ var ( coverRx = regexp.MustCompile(`^\s{4}Stream #\d+:\d+: (Video):.*`) ) -func parseOutput(output string) map[string]string { +func (e *ffmpegExtractor) parseOutput(output string) map[string]string { outputs := map[string]string{} all := inputRegex.FindAllStringSubmatchIndex(output, -1) for i, loc := range all { @@ -85,7 +85,7 @@ func parseOutput(output string) map[string]string { return outputs } -func extractMetadata(filePath, info string) (*ffmpegMetadata, error) { +func (e *ffmpegExtractor) extractMetadata(filePath, info string) (*ffmpegMetadata, error) { m := &ffmpegMetadata{} m.filePath = filePath m.tags = map[string]string{} @@ -147,7 +147,7 @@ func (m *ffmpegMetadata) parseInfo(info string) { } // Inputs will always be absolute paths -func createProbeCommand(inputs []string) []string { +func (e *ffmpegExtractor) createProbeCommand(inputs []string) []string { split := strings.Split(conf.Server.ProbeCommand, " ") args := make([]string, 0) diff --git a/scanner/metadata/ffmpeg_test.go b/scanner/metadata/ffmpeg_test.go index 62451d1d4..c5d36ec82 100644 --- a/scanner/metadata/ffmpeg_test.go +++ b/scanner/metadata/ffmpeg_test.go @@ -5,11 +5,14 @@ import ( . "github.com/onsi/gomega" ) -var _ = Describe("ffmpegMetadata", func() { +var _ = Describe("ffmpegExtractor", func() { + var e *ffmpegExtractor + BeforeEach(func() { + e = &ffmpegExtractor{} + }) // TODO Need to mock `ffmpeg` - XContext("ExtractAllMetadata", func() { + XContext("Extract", func() { It("correctly parses metadata from all files in folder", func() { - e := &ffmpegExtractor{} mds, err := e.Extract("tests/fixtures/test.mp3", "tests/fixtures/test.ogg") Expect(err).NotTo(HaveOccurred()) Expect(mds).To(HaveLen(2)) @@ -57,7 +60,7 @@ Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/ Duration: 00:00:01.02, start: 0.000000, bitrate: 477 kb/s Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 192 kb/s Stream #0:1: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 600x600 [SAR 1:1 DAR 1:1], 90k tbr, 90k tbn, 90k tbc` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.HasPicture()).To(BeTrue()) }) @@ -70,7 +73,7 @@ Input #0, ogg, from '/Users/deluan/Music/iTunes/iTunes Media/Music/_Testes/Jamai ALBUM : Jamaican In New York metadata_block_picture: AAAAAwAAAAppbWFnZS9qcGVnAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Id/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ TITLE : Jamaican In New York (Album Version)` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.HasPicture()).To(BeTrue()) }) @@ -79,7 +82,7 @@ Input #0, ogg, from '/Users/deluan/Music/iTunes/iTunes Media/Music/_Testes/Jamai Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3': Duration: 00:00:01.02, start: 0.000000, bitrate: 477 kb/s Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 192 kb/s` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.BitRate()).To(Equal(192)) }) @@ -89,7 +92,7 @@ Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/ Metadata: compilation : 1 Duration: 00:05:02.63, start: 0.000000, bitrate: 140 kb/s` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Compilation()).To(BeTrue()) }) @@ -97,7 +100,7 @@ Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/ const output = ` Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3': Duration: 00:05:02.63, start: 0.000000, bitrate: 140 kb/s` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Duration()).To(BeNumerically("~", 302.63, 0.001)) }) @@ -110,7 +113,7 @@ Input #0, ogg, from './01-02 Drive (Teku).opus': Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp Metadata: TITLE : Drive (Teku)` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Title()).To(Equal("Drive (Teku)")) }) @@ -122,7 +125,7 @@ Input #0, mp3, from 'groovin.mp3': Duration: 00:03:34.28, start: 0.025056, bitrate: 323 kb/s Metadata: title : garbage` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Title()).To(Equal("Groovin' (feat. Daniel Sneijers, Susanne Alt)")) }) @@ -139,7 +142,7 @@ Input #0, flac, from '/Users/deluan/Downloads/06. Back In Black.flac': TRACKTOTAL : 10 track : 6 Duration: 00:04:16.00, start: 0.000000, bitrate: 995 kb/s` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Title()).To(Equal("Back In Black")) Expect(md.Album()).To(Equal("Back In Black")) Expect(md.Genre()).To(Equal("Hard Rock")) @@ -183,7 +186,7 @@ Tracklist: 07. Wunderbar 08. Quarta Dimensão ` - md, _ := extractMetadata("tests/fixtures/test.mp3", outputWithMultilineComment) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", outputWithMultilineComment) Expect(md.Comment()).To(Equal(expectedComment)) }) @@ -200,7 +203,7 @@ Input #0, mp3, from '/Users/deluan/Downloads/椎名林檎 - 加爾基 精液 栗 artist_sort : Shiina, Ringo ALBUMARTISTSORT : Shiina, Ringo ` - md, _ := extractMetadata("tests/fixtures/test.mp3", output) + md, _ := e.extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Title()).To(Equal("ドツペルゲンガー")) Expect(md.Album()).To(Equal("加爾基 精液 栗ノ花")) Expect(md.Artist()).To(Equal("椎名林檎")) @@ -212,33 +215,8 @@ Input #0, mp3, from '/Users/deluan/Downloads/椎名林檎 - 加爾基 精液 栗 }) }) - Context("parseYear", func() { - It("parses the year correctly", func() { - var examples = map[string]int{ - "1985": 1985, - "2002-01": 2002, - "1969.06": 1969, - "1980.07.25": 1980, - "2004-00-00": 2004, - "2013-May-12": 2013, - "May 12, 2016": 0, - } - for tag, expected := range examples { - md := &ffmpegMetadata{} - md.tags = map[string]string{"date": tag} - Expect(md.Year()).To(Equal(expected)) - } - }) - - It("returns 0 if year is invalid", func() { - md := &ffmpegMetadata{} - md.tags = map[string]string{"date": "invalid"} - Expect(md.Year()).To(Equal(0)) - }) - }) - It("creates a valid command line", func() { - args := createProbeCommand([]string{"/music library/one.mp3", "/music library/two.mp3"}) + args := e.createProbeCommand([]string{"/music library/one.mp3", "/music library/two.mp3"}) Expect(args).To(Equal([]string{"ffmpeg", "-i", "/music library/one.mp3", "-i", "/music library/two.mp3", "-f", "ffmetadata"})) }) diff --git a/scanner/metadata/metadata_suite_test.go b/scanner/metadata/metadata_suite_test.go new file mode 100644 index 000000000..d8186e14c --- /dev/null +++ b/scanner/metadata/metadata_suite_test.go @@ -0,0 +1,17 @@ +package metadata + +import ( + "testing" + + "github.com/deluan/navidrome/log" + "github.com/deluan/navidrome/tests" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestScanner(t *testing.T) { + tests.Init(t, true) + log.SetLevel(log.LevelCritical) + RegisterFailHandler(Fail) + RunSpecs(t, "Metadata Suite") +} diff --git a/scanner/metadata/metadata_test.go b/scanner/metadata/metadata_test.go new file mode 100644 index 000000000..d68f59e8a --- /dev/null +++ b/scanner/metadata/metadata_test.go @@ -0,0 +1,33 @@ +package metadata + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("ffmpegMetadata", func() { + Context("parseYear", func() { + It("parses the year correctly", func() { + var examples = map[string]int{ + "1985": 1985, + "2002-01": 2002, + "1969.06": 1969, + "1980.07.25": 1980, + "2004-00-00": 2004, + "2013-May-12": 2013, + "May 12, 2016": 0, + } + for tag, expected := range examples { + md := &baseMetadata{} + md.tags = map[string]string{"date": tag} + Expect(md.Year()).To(Equal(expected)) + } + }) + + It("returns 0 if year is invalid", func() { + md := &baseMetadata{} + md.tags = map[string]string{"date": "invalid"} + Expect(md.Year()).To(Equal(0)) + }) + }) +}) diff --git a/scanner/metadata/taglib_test.go b/scanner/metadata/taglib_test.go new file mode 100644 index 000000000..3c14f84a4 --- /dev/null +++ b/scanner/metadata/taglib_test.go @@ -0,0 +1,50 @@ +package metadata + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("taglibExtractor", func() { + Context("Extract", func() { + It("correctly parses metadata from all files in folder", func() { + e := &taglibExtractor{} + mds, err := e.Extract("tests/fixtures/test.mp3", "tests/fixtures/test.ogg") + Expect(err).NotTo(HaveOccurred()) + Expect(mds).To(HaveLen(2)) + + m := mds["tests/fixtures/test.mp3"] + Expect(m.Title()).To(Equal("Song")) + Expect(m.Album()).To(Equal("Album")) + Expect(m.Artist()).To(Equal("Artist")) + Expect(m.AlbumArtist()).To(Equal("Album Artist")) + Expect(m.Composer()).To(Equal("Composer")) + // TODO This is not working. See https://github.com/taglib/taglib/issues/971 + //Expect(m.Compilation()).To(BeTrue()) + Expect(m.Genre()).To(Equal("Rock")) + Expect(m.Year()).To(Equal(2014)) + n, t := m.TrackNumber() + Expect(n).To(Equal(2)) + Expect(t).To(Equal(10)) + n, t = m.DiscNumber() + Expect(n).To(Equal(1)) + Expect(t).To(Equal(2)) + Expect(m.HasPicture()).To(BeTrue()) + Expect(m.Duration()).To(Equal(float32(1))) + Expect(m.BitRate()).To(Equal(192)) + Expect(m.FilePath()).To(Equal("tests/fixtures/test.mp3")) + Expect(m.Suffix()).To(Equal("mp3")) + Expect(m.Size()).To(Equal(int64(60845))) + + m = mds["tests/fixtures/test.ogg"] + Expect(err).To(BeNil()) + Expect(m.Title()).To(BeEmpty()) + Expect(m.HasPicture()).To(BeFalse()) + Expect(m.Duration()).To(Equal(float32(3))) + Expect(m.BitRate()).To(Equal(10)) + Expect(m.Suffix()).To(Equal("ogg")) + Expect(m.FilePath()).To(Equal("tests/fixtures/test.ogg")) + Expect(m.Size()).To(Equal(int64(4408))) + }) + }) +})