From 4ceaea773228262b34997b75b9d321bd51a1b6ee Mon Sep 17 00:00:00 2001 From: Deluan Date: Tue, 18 Feb 2020 09:57:33 -0500 Subject: [PATCH] fix: extract stream level metadata --- scanner/metadata_ffmpeg.go | 37 +++++++++++++++++++-------------- scanner/metadata_test.go | 42 ++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/scanner/metadata_ffmpeg.go b/scanner/metadata_ffmpeg.go index 69236fa9e..76d0f0df5 100644 --- a/scanner/metadata_ffmpeg.go +++ b/scanner/metadata_ffmpeg.go @@ -143,21 +143,21 @@ func isAudioFile(extension string) bool { var ( tagsRx = map[*regexp.Regexp]string{ - regexp.MustCompile(`(?i)^\s{4}compilation\s+:(.*)`): "compilation", - regexp.MustCompile(`(?i)^\s{4}genre\s+:\s(.*)`): "genre", - regexp.MustCompile(`(?i)^\s{4}title\s+:\s(.*)`): "title", - regexp.MustCompile(`(?i)^\s{4}comment\s+:\s(.*)`): "comment", - regexp.MustCompile(`(?i)^\s{4}artist\s+:\s(.*)`): "artist", - regexp.MustCompile(`(?i)^\s{4}album_artist\s+:\s(.*)`): "album_artist", - regexp.MustCompile(`(?i)^\s{4}TCM\s+:\s(.*)`): "composer", - regexp.MustCompile(`(?i)^\s{4}album\s+:\s(.*)`): "album", - regexp.MustCompile(`(?i)^\s{4}track\s+:\s(.*)`): "trackNum", - regexp.MustCompile(`(?i)^\s{4}tracktotal\s+:\s(.*)`): "trackTotal", - regexp.MustCompile(`(?i)^\s{4}disc\s+:\s(.*)`): "discNum", - regexp.MustCompile(`(?i)^\s{4}disctotal\s+:\s(.*)`): "discTotal", - regexp.MustCompile(`(?i)^\s{4}TPA\s+:\s(.*)`): "discNum", - regexp.MustCompile(`(?i)^\s{4}date\s+:\s(.*)`): "year", - regexp.MustCompile(`^\s{4}Stream #\d+:\d+: (.+):\s`): "hasPicture", + regexp.MustCompile(`(?i)^\s{4,6}compilation\s+:(.*)`): "compilation", + regexp.MustCompile(`(?i)^\s{4,6}genre\s+:\s(.*)`): "genre", + regexp.MustCompile(`(?i)^\s{4,6}title\s+:\s(.*)`): "title", + regexp.MustCompile(`(?i)^\s{4,6}comment\s+:\s(.*)`): "comment", + regexp.MustCompile(`(?i)^\s{4,6}artist\s+:\s(.*)`): "artist", + regexp.MustCompile(`(?i)^\s{4,6}album_artist\s+:\s(.*)`): "album_artist", + regexp.MustCompile(`(?i)^\s{4,6}TCM\s+:\s(.*)`): "composer", + regexp.MustCompile(`(?i)^\s{4,6}album\s+:\s(.*)`): "album", + regexp.MustCompile(`(?i)^\s{4,6}track\s+:\s(.*)`): "trackNum", + regexp.MustCompile(`(?i)^\s{4,6}tracktotal\s+:\s(.*)`): "trackTotal", + regexp.MustCompile(`(?i)^\s{4,6}disc\s+:\s(.*)`): "discNum", + regexp.MustCompile(`(?i)^\s{4,6}disctotal\s+:\s(.*)`): "discTotal", + regexp.MustCompile(`(?i)^\s{4,6}TPA\s+:\s(.*)`): "discNum", + regexp.MustCompile(`(?i)^\s{4,6}date\s+:\s(.*)`): "year", + regexp.MustCompile(`^\s{4}Stream #\d+:\d+: (Video):.*pic\)$`): "hasPicture", } durationRx = regexp.MustCompile(`^\s\sDuration: ([\d.:]+).*bitrate: (\d+)`) @@ -168,7 +168,14 @@ func (m *Metadata) parseInfo(info string) { scanner := bufio.NewScanner(reader) for scanner.Scan() { line := scanner.Text() + if len(line) == 0 { + continue + } for rx, tag := range tagsRx { + // Skip when the tag was previously found + if _, ok := m.tags[tag]; ok { + continue + } match := rx.FindStringSubmatch(line) if len(match) > 0 { m.tags[tag] = match[1] diff --git a/scanner/metadata_test.go b/scanner/metadata_test.go index 81803b709..7b926004b 100644 --- a/scanner/metadata_test.go +++ b/scanner/metadata_test.go @@ -67,31 +67,55 @@ var _ = Describe("Metadata", func() { }) Context("extractMetadata", func() { + It("detects embedded cover art correctly", func() { + const output = ` +Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3': + Metadata: + compilation : 1 + 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 (Baseline), gray(bt470bg/unknown/unknown), 600x600 [SAR 72:72 DAR 1:1], 90k tbr, 90k tbn, 90k tbc (attached pic)` + md, _ := extractMetadata("tests/fixtures/test.mp3", output) + Expect(md.HasPicture()).To(BeTrue()) + }) + It("parses correctly the compilation tag", func() { - const outputWithOverlappingTitleTag = ` + const output = ` Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3': Metadata: compilation : 1 Duration: 00:05:02.63, start: 0.000000, bitrate: 140 kb/s` - md, _ := extractMetadata("tests/fixtures/test.mp3", outputWithOverlappingTitleTag) + md, _ := extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Compilation()).To(BeTrue()) }) - It("parses correct the title without overlapping with the stream tag", func() { - const outputWithOverlappingTitleTag = ` + It("parses stream level tags", func() { + const output = ` +Input #0, ogg, from './01-02 Drive (Teku).opus': + Metadata: + ALBUM : Hot Wheels Acceleracers Soundtrack + Duration: 00:03:37.37, start: 0.007500, bitrate: 135 kb/s + Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp + Metadata: + TITLE : Drive (Teku)` + md, _ := extractMetadata("tests/fixtures/test.mp3", output) + Expect(md.Title()).To(Equal("Drive (Teku)")) + }) + + It("does not overlap top level tags with the stream level tags", func() { + const output = ` Input #0, mp3, from 'groovin.mp3': Metadata: title : Groovin' (feat. Daniel Sneijers, Susanne Alt) Duration: 00:03:34.28, start: 0.025056, bitrate: 323 kb/s Metadata: - title : cover -At least one output file must be specified` - md, _ := extractMetadata("tests/fixtures/test.mp3", outputWithOverlappingTitleTag) + title : garbage` + md, _ := extractMetadata("tests/fixtures/test.mp3", output) Expect(md.Title()).To(Equal("Groovin' (feat. Daniel Sneijers, Susanne Alt)")) }) It("ignores case in the tag name", func() { - const outputWithOverlappingTitleTag = ` + const output = ` Input #0, flac, from '/Users/deluan/Downloads/06. Back In Black.flac': Metadata: ALBUM : Back In Black @@ -103,7 +127,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", outputWithOverlappingTitleTag) + md, _ := 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"))