When parsing .lrc files, retain a line without timestamp following one with a timestamp.
Display empty lines within the lyrics (after the first timestamp has occurred).
Not displaying tags at the start of the file [la:ger], etc. and lines without timestamp before the first timestamp would be a sensible solution imho.
Problem solved:
Line breaks are sometimes used in .lrc files to display 2 different lines at the same time.
Either when there’s a main singer and background vocals or when the original language + a translation are to be displayed at the same time, below one another.
Empty lines retain the verse structure of the lyrics (but it’s a matter of taste if they are to be displayed or not, so this could be optional).
Brought benefits:
It would mean that Symfonium can properly display lyrics with 2 lines of text per timestamp and retains the verse structure of the lyrics (when present in the file).
Other application solutions:
MusicBee handles .lrc files in the manner I described.
Tags and lines without timestamp at the start of the .lrc file are ignored, but after the first timestamp, line breaks and lines without timestamp are displayed at the same time as the previous timestamp (see screenshots).
Additional description and context:
I’ve added 4 screenshots that show how MusicBee and Symfonium handle 2 example songs + .lrc files. The first one with 2 interweaving vocals and the second one with original language + translation. I’ll provide the content of the .lrc files in a comment with formatting.
I admit that lyrics like these are fairly rare so I’d understand if you don’t want to do additional parsing to support them.
[0:10.308]Are you going to Scarborough Fair?
[0:17.568]Parsley, sage, rosemary and thyme;
[0:26.508]Remember me to one who lives there -
[0:34.008]She once was a true love of mine.
[0:43.848]Tell her to make me a cambric shirt:
(On the side of a hill in the deep forest green,)
[0:51.288]Parsley, sage, rosemary and thyme;
(Tracing a sparrow on snow-crested ground,)
[1:00.048]Without no seams nor needlework,
(Blankets and bedclothes, a child of the mountains)
[1:07.788]Then she'll be a true love of mine.
(Sleeps unaware of the clarion call)
[1:17.388]Tell her to find me an acre of land:
(On the side of a hill, a sprinkling of leaves.)
[1:24.708]Parsley, sage, rosemary and thyme;
(Washed is the ground with so many tears,)
[1:33.528]Between the salt water and the sea strand,
(A soldier cleans and polishes a gun.)
[1:40.728]Then she'll be a true love of mine.
[1:50.662]Tell her to reap it in a sickle of leather:
(War bellows blazing in scarlet battalions,)
[1:58.222]Parsley, sage, rosemary and thyme;
(Generals order their soldiers to kill)
[2:07.042]And gather it all in a bunch of heather,
(And to fight for a cause they've long ago forgotten.)
[2:14.842]Then she'll be a true love of mine.
[2:24.622]Are you going to Scarborough Fair?
[2:32.062]Parsley, sage, rosemary and thyme;
[2:41.242]Remember me to one who lives there -
[2:48.982]She once was a true love of mine.
Second .lrc file:
[0:00.000]Haritsumeta yumi no
The stretching bow
[0:06.696]Furueru tsuru yo
Of its trembling string
[0:11.988]Tsuki no hikari ni zawameku
Disturbed in the moonlight
[0:18.276]Omae no kokoro
Is your heart
[0:24.216]Togisumasareta
The well-sharpened blade
[0:30.044]Yaiba no utsukushii
Has a beautiful tip
[0:35.044]Sono kissaki ni yoku nita
That resembles to it
[0:41.504]Sonata no yokogao
Is your profile
[0:47.444]Kanashimi to ikari ni
In the grief and anger
[0:52.930]Hisomu makoto no kokoro wo
Your true heart lurks within
[0:59.024]Shiru wa mori no sei-i
You’re understood by the Spirits of the Forest
[1:05.384]Mononoke-tachi dake
Only the Mononoke
[1:11.144]Mononoke-tachi dake
Only the Mononoke
Interesting, I have never encountered that case in the wild. However I’d limit it to repeating the following line and that only if it’s not an empty line. Otherwise the resulting formatting could turn ugly quickly.
The multi timestamp is frequent to avoid repeating the same text over and over and the timestamps can be at different positions in the lyrics with other text in the middle
For example
[1][5][10] Hello
[2] Tata
[3] Titi
[8] Plip
[12] Plop
[0:00.000] [0:01.000] [0:02.000]Haritsumeta yumi no
The stretching bow
and not the empty line below them as well.
Also I meant not to repeat the empty line in a case like this:
[0:00.000] [0:01.000] [0:02.000]Haritsumeta yumi no
I just tried it and MusicBee displays:
[0:00.000] [0:03.000] [0:05.000]Haritsumeta yumi no
The stretching bow
[0:06.696]Furueru tsuru yo
Of its trembling string
[0:11.988]Tsuki no hikari ni zawameku
So it does not repeat the 2nd part of the multi-line (only the line with multiple timestamps) and instead only displays it at the same time as the first occurence.
Probably to avoid this:
After thinking about it while watching TV I’m not sure it’s worth the effort to repeat both parts of multi-lines. Multi-lines are already rare and if you deliberately create them I’d guess you’re smart enough not to use repeated lines as part of a multi-line which compounds the required parsing effort.
I know, though I’m not really a fan of them as I don’t know a single piece of software that allows to easily (re-)sync those repeated lines (except for applying a global offset to all timestamps). Couple bytes saved and a lot of headache won imho. Also they mess with the lyrics structure when you view them in a text editor. For example if the first line of each verse is the same but the rest differs, you get one repeated line and then a bunch of incomplete verses. It’s more efficient but it bothers me visually.
I’d imagine something like this:
Check if the line starts with multiple timestamps.
Check if the following line does not contain a timestamp and is also not only a newline.
Group the repeated line and the following line together if it’s text.
Insert both of them at all timestamps contained in the repeated line.
Keeping the correct order becomes tricky by supporting multi-lines and empty lines tho as you have to treat all lines between 2 lines that start with timestamps (including the first timestamp line and excluding the second one) as one group to insert other lines before/after to avoid possibly breaking other multi-lines.
I’m probably overlooking a couple other cases that complicate it further tho so I don’t think it’s worth the effort. If multi-lines are displayed as well as in MusicBee that would be good enough in my opinion, considering how rare they are.
Maybe ask ChatGPT to sum this up, turned out as a bit of a wall of text.
Edit: After thinking about it some more I realized that empty lines without timestamps lead to problems with repeated lines as you cannot know if the empty line is supposed to be before (end of verse) or after (start of verse) an inserted line:
[0:00.000][0:20.333]Haritsumeta yumi no
[0:18.276]Omae no kokoro
Is your heart
[0:24.216]Togisumasareta
The well-sharpened blade
Could either lead to:
[0:00.000]Haritsumeta yumi no
[0:18.276]Omae no kokoro
Is your heart
[0:20.333]Haritsumeta yumi no
[0:24.216]Togisumasareta
The well-sharpened blade
Or to
[0:00.000]Haritsumeta yumi no
[0:18.276]Omae no kokoro
Is your heart
[0:20.333]Haritsumeta yumi no
[0:24.216]Togisumasareta
The well-sharpened blade
In a perfect world a dual approach might work, where empty lines are kept if the lyrics do not contain repeated lines (no insertions needed) and removed if they do, which would avoid this problem. I’ll probably add some more thoughts when I wake up tomorrow, so brace yourselves.
You still need to parse the [offset:] to get the offset
For empty lines people often want them (including in non synced) but after a few discussions I only leave one so if there’s 3 empty lines only 1 is kept.
Same for multi lines.
For @655321 a line without a timestamp can only be related to the previous timesamp and not a future one.
Yes, “tags” are not part of that and always taken into account (even in the middle of the file)
I do not skip any empty line for unsynchronized lyrics, I was just talking about multi lines for a single timestamp (or a set of timestamps)
To keep empty lines separating lyrics lines but it’s fine to strip trailing empty lines at the end of the lyrics and reduce repeated empty lines within them to one.
But that only works well when there are no repeated lines mixed in.
What I meant is that this:
[la:ger]
[offset:+100]
some random text
[0:18.276]Omae no kokoro
Is your heart
[0:24.216]Togisumasareta
The well-sharpened blade
Should end up like this:
18376: "Omae no kokoro\nIs your heart\n"
24316: "Togisumasareta\n\nThe well-sharpened blade"
Apply the offset, do not display tags, empty lines and text without timestamps before the first line with a timestamp at the start of the .lrc file, reduce consecutive empty lines to one empty line, remove trailing empty lines but keep (single) empty lines within the lyrics.
Many people aren’t even aware of the fact that you can have newlines at the end of a text file as most text editors only indicate them by increasing the line number on the left (if the editor even has that, looking at Notepad).
The problem with repeated multi-lines I had in mind yesterday was this:
[0:01.00]repeat me
repeat me too
[0:02.00]some line1
[0:03.00]some line2
[0:04.00]repeat me
repeat me too
[0:05.00]repeat me
repeat me too
[0:06.00]some line4
Would yield:
100: "repeat me\nrepeat me too"
200: "some line1"
300: "some line2"
400: "repeat me\nrepeat me too\n"
500: "repeat me\nrepeat me too"
600: "some line4"
However if it was saved like this instead:
[0:01.00][0:04.00][0:05.00]repeat me
repeat me too
[0:02.00]some line1
[0:03.00]some line2
[0:06.00]some line4
It would yield:
100: "repeat me\nrepeat me too"
200: "some line1"
300: "some line2\n"
400: "repeat me\nrepeat me too"
500: "repeat me\nrepeat me too"
600: "some line4"
But that can be solved by saving it like this (which admittedly saves fewer characters):
[0:01.00][0:05.00]repeat me
repeat me too
[0:02.00]some line1
[0:03.00]some line2
[0:04.00]repeat me
repeat me too
[0:06.00]some line4
Which would once again correctly yield:
100: "repeat me\nrepeat me too"
200: "some line1"
300: "some line2"
400: "repeat me\nrepeat me too\n"
500: "repeat me\nrepeat me too"
600: "some line4"
So I don’t see a problem with (properly created) repeated multi-lines any more, or rather if there are problems, it’s the fault of whoever created them poorly.