diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 94a5b7b67e..e74e5fe11b 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -245,9 +245,10 @@ class ID3File(File): 'MVIN': re.compile(r'^(?P\d+)(?:/(?P\d+))?$') } - __lrc_line_re_parse = re.compile(r'(\[\d\d:\d\d\.\d\d\d\])') - __lrc_syllable_re_parse = re.compile(r'(<\d\d:\d\d\.\d\d\d>)') - __lrc_both_re_parse = re.compile(r'(\[\d\d:\d\d\.\d\d\d\]|<\d\d:\d\d\.\d\d\d>)') + __lrc_time_format_re = r'\d+:\d{1,2}(?:.\d+)?' + __lrc_line_re_parse = re.compile(r'(\[' + __lrc_time_format_re + r'\])') + __lrc_syllable_re_parse = re.compile(r'(<' + __lrc_time_format_re + r'>)') + __lrc_both_re_parse = re.compile(r'(\[' + __lrc_time_format_re + r'\]|<' + __lrc_time_format_re + r'>)') def __init__(self, filename): super().__init__(filename) @@ -765,8 +766,8 @@ def _parse_lrc_text(self, text): timestamp_and_lyrics = batched(self.__lrc_both_re_parse.split(text)[1:], 2) for timestamp, lyrics in timestamp_and_lyrics: - minutes, seconds, ms = timestamp[1:-1].replace(".", ":").split(':') - milliseconds = int(minutes) * 60 * 1000 + int(float('%s.%s' % (seconds, ms)) * 1000) + minutes, seconds = timestamp[1:-1].split(':') + milliseconds = int(minutes) * 60 * 1000 + int(float(seconds) * 1000) sylt_lyrics.append((lyrics, milliseconds)) # Remove frames with no lyrics and a repeating timestamp diff --git a/test/formats/test_id3.py b/test/formats/test_id3.py index c90ed75dad..ff9dbc0fbb 100644 --- a/test/formats/test_id3.py +++ b/test/formats/test_id3.py @@ -799,6 +799,10 @@ def test_syncedlyrics_converting_to_sylt(self): "[00:00.000]Test lyrics with\n[01:00.000]only line time stamps", "<00:00.000>Test lyrics with<01:00.000>only syllable time stamps", "[00:00.000]<00:00.000>Test extra\n<00:00.750>[00:00.750]<00:00.750>timestamp<00:01.500>", + "[00:01.00]<00:01.00>Test lyrics with two\n[00:01.75]<00:01.75>digit ms", + "[01:01.0]<01:01.000>Test lyrics with different\n[01:01.8]<01:01.7506>digit ms", + "[2:1.0]<2:1.0>Test lyrics with single digits\n[2:2]<2:2>or no ms", + "[300:1.000]<300:1.000>Test lyrics with long minutes", "Test invalid[00:00.000]input\nTest invalid[00:01.000]input", "Test lyrics with no timestamps") correct_sylt = ( @@ -806,6 +810,10 @@ def test_syncedlyrics_converting_to_sylt(self): [("Test lyrics with\n", 0), ("only line time stamps", 60 * 1000)], [("Test lyrics with", 0), ("only syllable time stamps", 60 * 1000)], [("Test extra\n", 0), ("timestamp", 750), ("", 1500)], + [("Test lyrics with two\n", 1000), ("digit ms", 1750)], + [("Test lyrics with different\n", 61000), ("digit ms", 61750)], + [("Test lyrics with single digits\n", 121000), ("or no ms", 122000)], + [("Test lyrics with long minutes", (300*60+1)*1000)], [("input\nTest invalid", 0), ("input", 1000)], []) for lrc, correct_sylt in zip(lrc, correct_sylt):