diff --git a/model/lyrics_lrc.go b/model/lyrics_lrc.go index 6fde0c8f5..2cccb9d51 100644 --- a/model/lyrics_lrc.go +++ b/model/lyrics_lrc.go @@ -189,6 +189,7 @@ func parseEnhancedLine(text string) (string, []Cue) { segments := make([]segment, 0, len(matches)) var rawValue strings.Builder + var trailingEnd *int64 for i, match := range matches { timeMs, err := parseTime( // Rewrite <...> as [...] so parseTime can handle it with the same logic @@ -217,6 +218,9 @@ func parseEnhancedLine(text string) (string, []Cue) { word := text[textStart:textEnd] if word == "" { + if i == len(matches)-1 { + trailingEnd = &timeMs + } continue } @@ -258,6 +262,10 @@ func parseEnhancedLine(text string) (string, []Cue) { }) } + if trailingEnd != nil && len(cues) > 0 { + cues[len(cues)-1].End = trailingEnd + } + return strings.TrimSpace(finalRaw), cues } diff --git a/model/lyrics_lrc_test.go b/model/lyrics_lrc_test.go index 38f03587a..87514caf1 100644 --- a/model/lyrics_lrc_test.go +++ b/model/lyrics_lrc_test.go @@ -188,6 +188,42 @@ var _ = Describe("parseLRC", func() { })) }) + It("should use a trailing Enhanced LRC marker as the end of the last word", func() { + lyrics, err := parseLRC("xxx", "[00:01.00]<00:01.00>Some <00:01.50>lyrics<00:02.00>\n[00:30.00]Instrumental over") + Expect(err).ToNot(HaveOccurred()) + Expect(lyrics.Line).To(HaveLen(2)) + + t1000, t1500, t2000 := int64(1000), int64(1500), int64(2000) + line := lyrics.Line[0] + Expect(line.Value).To(Equal("Some lyrics")) + Expect(line.End).To(Equal(&t2000)) + Expect(line.Cue).To(Equal([]Cue{ + {Start: &t1000, End: &t1500, Value: "Some ", ByteStart: 0, ByteEnd: 4}, + {Start: &t1500, End: &t2000, Value: "lyrics", ByteStart: 5, ByteEnd: 10}, + })) + }) + + It("should shift a trailing Enhanced LRC marker for repeated line occurrences", func() { + lyrics, err := parseLRC("xxx", "[00:10.00][00:30.00]<00:10.10>Hello <00:10.50>world<00:10.90>") + Expect(err).ToNot(HaveOccurred()) + Expect(lyrics.Line).To(HaveLen(2)) + + t10100, t10500, t10900 := int64(10100), int64(10500), int64(10900) + t30100, t30500, t30900 := int64(30100), int64(30500), int64(30900) + + Expect(lyrics.Line[0].End).To(Equal(&t10900)) + Expect(lyrics.Line[0].Cue).To(Equal([]Cue{ + {Start: &t10100, End: &t10500, Value: "Hello ", ByteStart: 0, ByteEnd: 5}, + {Start: &t10500, End: &t10900, Value: "world", ByteStart: 6, ByteEnd: 10}, + })) + + Expect(lyrics.Line[1].End).To(Equal(&t30900)) + Expect(lyrics.Line[1].Cue).To(Equal([]Cue{ + {Start: &t30100, End: &t30500, Value: "Hello ", ByteStart: 0, ByteEnd: 5}, + {Start: &t30500, End: &t30900, Value: "world", ByteStart: 6, ByteEnd: 10}, + })) + }) + It("should shift inline ELRC word timestamps for each repeated line occurrence", func() { lyrics, err := parseLRC("xxx", "[00:10.00][00:30.00]<00:10.10>Hello <00:10.50>world") Expect(err).ToNot(HaveOccurred())