diff --git a/LrcParser.Tests/Parser/Lrc/Lines/LrcLyricParserTest.cs b/LrcParser.Tests/Parser/Lrc/Lines/LrcLyricParserTest.cs index be730a4..2cdd150 100644 --- a/LrcParser.Tests/Parser/Lrc/Lines/LrcLyricParserTest.cs +++ b/LrcParser.Tests/Parser/Lrc/Lines/LrcLyricParserTest.cs @@ -105,6 +105,17 @@ public void TestDecode(string lyric, LrcLyric expected) TimeTags = [], }, ], + // Don't parse word time tags if multiple line time tags are found, as this is unsupported by LRC. + // Instead, return the unparsed line without the line time and no word time tags. + [ + "[00:17.00][00:18.00] <00:00.00>帰<00:01.00>り<00:02.00>道<00:03.00>は", + new LrcLyric + { + Text = "<00:00.00>帰<00:01.00>り<00:02.00>道<00:03.00>は", + StartTimes = [17000, 18000], + TimeTags = [], + }, + ], }; [TestCaseSource(nameof(testEncodeSource))] diff --git a/LrcParser/Parser/Lrc/Lines/LrcLyricParser.cs b/LrcParser/Parser/Lrc/Lines/LrcLyricParser.cs index 69c6ff2..0123e76 100644 --- a/LrcParser/Parser/Lrc/Lines/LrcLyricParser.cs +++ b/LrcParser/Parser/Lrc/Lines/LrcLyricParser.cs @@ -1,6 +1,7 @@ // Copyright (c) karaoke.dev . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using LrcParser.Model; using LrcParser.Parser.Lines; using LrcParser.Parser.Lrc.Metadata; using LrcParser.Parser.Lrc.Utils; @@ -14,8 +15,28 @@ public override bool CanDecode(string text) public override LrcLyric Decode(string text) { - var (startTimes, lyricText) = LrcStartTimeUtils.SplitLyricAndTimeTag(text); - var (lyric, timeTags) = LrcTimedTextUtils.TimedTextToObject(lyricText); + var (startTimes, rawLyric) = LrcStartTimeUtils.SplitLyricAndTimeTag(text); + + // If there are multiple start times, it is possible that the given word time tags are incompatible with one or more start times. + // For example, if a line starts at both [01:00.00] and [02:00.00], + // word time tags with the values <01:10.00> and <01:20.00> would be incompatible with the second start time. + // As there isn't an official LRC spec, this isn't clearly defined. + // While the format is technically valid, we chose a reasonable behavior of ignoring the word time tags in this case + // and returning the line as-is without parsing the word time tags. + // The same applies to lines that have no start times: + // As there might be lines like `Every <00:07.56> night`, the first word would not have a start time, + // so we chose the same approach of ignoring the word time tags in this case. + if (startTimes.Length is 0 or > 1) + { + return new LrcLyric + { + Text = rawLyric, + StartTimes = startTimes, + TimeTags = new SortedDictionary() + }; + } + + var (lyric, timeTags) = LrcTimedTextUtils.TimedTextToObject(rawLyric); return new LrcLyric {