Let Brackets be in when syncing lyrics

Feature description:

Hey,
So my problem is that i personally use the Genius formatting for my synced lyrics, which means it looks like:
“[Chorus]

[Verse 1]
…”

The problem is that the App doesnt accept those brackets as normal Words, which means they get removed since they dont have a timestamp infront of it. Is it possible to make the app not do it? :frowning:

Problem solved:

The problem where i can format the lyrics properly, or not see whos also singing/rapping in the verse.

Brought benefits:

Gives more freedom with your Lyrics formatting

Other application solutions:

 
I don’t know how they solved it exactly, but I know that Musicolet doesnt have this problem.
 

Additional description and context:

 

 

Screenshots / Mockup:

    

If you take a look at the wikipedia page for the .lrc file format, you’ll find:

ID tags may optionally appear before the lyrics,[3] although some players may not recognize or simply ignore this[citation needed]. The format of an ID tag is [type:value], where type is the tag type and value its value (most often some text).

In my script lyrict for example, the tag_external mode allows adding such tags to external lyrics files. Example result:

[ar:Suzanne Vega]
[al:Beauty & Crime]
[ti:Pornographer's Dream]
[au:Suzanne Vega]
[length:03:24]
[00:16.133]She's a pornographer's dream, he said
[00:20.992]I knew what he meant

The reason why most players I know strip any lines that are enclosed in square brackets is to avoid displaying such tags which is usually unwanted.

The regex to filter could probably be adjusted to something like ^\[.*:.*\]$ (I don’t know the regex that’s used) to only strip text in square brackets that follows the general tag formatting but even then there’d be false positives if the genius information also contains a :. Or a highly specific regex that only matches each of the known/used tags could be thought up but it’s up to Tolriq if he’s willing to go to such lengths.

I remove the genius content in square brackets while syncing lyrics and only leave it in unsynced lyrics if I deem the information useful. But that’s a matter of personal preference.

Even if such text was not filtered, for synced lyrics the highlighting would probably be weird. When should these lines be highlighted? At the time of the next line with a timestamp? Or at the same time as the line that preceded them? I can’t think of either being visually pleasing.

@HaxCalibour how do you sync them?

Taking for example the first one on Genius right now is : https://genius.com/Genius-romanizations-aiscream-ai-scream-romanized-lyrics

And the data is [XXX : YYY] that’s tag style and is not supposed to be displayed. Can’t you just add the timestamp to those lines too ?

Hey,
The thing is, those brackets dont need timestamps. They are only to split the verses apart from each other so it doesnt look like a rundown block of text where i dont know which verse is whos.

Yes but as @655321 you are in a synced lyrics and those have no timestamp so how and where are they supposed to be displayed.
This is not something official in LRC so there’s no proper solution here.

Can you share a song with what you actually use to https://upload.symfonium.app

Can the genius headers simply be ignored but not deleted?

The Headers from Genius are usually in brackets & have a colon followed by artist name(s)

So

[Verse 1: James Carr]
[00:01.05] We lift our hands

Then the first line could be ignored but not removed so when showing the synced lyrics the timestamped line is highlighted or bolded on cue but the other text does not get a highlight or bold yet it still remains visible in the lyrics.

I like the headers Genius gives for lyrics as well. Sometimes I don’t know who’s singing what parts. Its nice to have that extra bit of info & synced lyrics never seem to have that.

Currently the only workarounds I had were:

  1. Headers immediately follow a timestamped lyric (brackets replaced with parentheses)

[00:03.05] We Lift our Hands
(Verse 1: James Carr)

Here the header is appearing after the lyrics are spoken which is a bit less than ideal.

  1. Hot swapping the timestamped lyric & header (brackets replaced with parentheses)

[00:03.05] (Verse 1: James Car)
We Lift our Hands

I had also requested users be able to flip between their synced & unsynced lyrics as lyrics can be saved (at least from the perspective of MP3TAG) in either

UNSYNCEDLYRICS (MP3, WAV, MP4)
OR
LYRICS (vorbis comment)

In any case I just wanted to see those headers that my Unsynced lyrics have as i find them useful.

The workarounds all work & evidently the formatting @HaxCalibour is using (which i believe matches the first example i gave) works in Musicolet somehow.

I haven’t gone about adding these headers to all my lyrics just yet though as I wanted to see how these feature requests played out.

I think skipping / ignoring the headers without removing themwould be most Ideal IMO but that may be a nightmare on your end :man_shrugging:t4:

Then all the other tags are shown too :wink:

And LRC files can be in disorder and a line can have multiple timestamps and be shown at many different places. LRC are complex.

1 Like

That one seems like the most promising workaround to me. Although two limitations come to mind. The first being that the header is highlighted at the same time as the line and the second being that other programs that do not support multi-lines in lyrics might strip everything after the linebreak and only display the header.

With a well built regex this transformation of the genius headers could probably be done automatically for all instances in a file.
If you give me a few examples I can see if I can come up with one (I like regex). Assuming you don’t already have one.

I’d be interested to know if Musicolet hides the tags at the beginning of the file or if it also displays these.

Edit: After thinking about it a bit more, I think it would be better to simply duplicate the timestamp of the following line and prepend it to the genius header like this:

[00:03.05] [Verse 1: James Car]
[00:03.05] We Lift our Hands

If I recall it correctly, when 2 lines share the same timestamp, Symfonium directly skips to the 2nd line and only highlights that. Could you try that and see if I’m correct?

With two lines sharing the same timestamp both are highlighted at the same time. When you toggle the setting to show the timestamps there is just one timestamp for the two lines.

If you use the brackets in the header as you have them here

That line gets erased from view

Unfortunately I don’t have a bunch of files for you to test with these are just some of the workarounds I had tried in my library when I was thinking about sort of merging my Synced & unsynced lyrics. I also tried adding a timestamp to those headers manually but that took more time & sometimes there isn’t even enough gap between lyrics to place them so it kind of kills the synced experience TBH

@HaxCalibour may have a number of files in this format:

[Chorus: James Carr]
[00:03.05] We Lift Our Hands

If they are able to provide those maybe you can work some regex magic to mass convert that to

[00:03.05] (Chorus: James Carr)
We Lift Our Hands

OR

[00:03.05] (Chorus: James Carr)
[00:03.05] We Lift Our Hands

or some other format where the header & lyric don’t both highlight

I’ve been playing with it for a bit. One thing that’s lost (unless I make the regex even more complicated) are instrumental passages followed by a header. Example:

[Guitar Solo]

[Bridge: Roger Waters]
[2:57.621]But it was only a fantasy

This would be turned into:

[Guitar Solo]

[2:57.621](Bridge: Roger Waters)
But it was only a fantasy

But then again, you should just create a timestamp for such instrumental passages anyhow.

However the lines with a header followed by a line with a timestamp are covered in this regex I’ve been playing around with:

^\[((?!(ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\]).*)\]\n(\[\d{1,2}:\d{1,2}\.\d{2,3}\])(.*)$

replace with

$3($1)\n$4

You could probably turn that into an Mp3tag action (if Mp3tag supports negative lookahead in it’s regex implementation) to mass edit embedded lyrics or turn it into a little script/batch file to mass edit external lyrics.

Here is my full example with all lrc tags (taken from wikipedia) which are ignored.

Let me know if you have ideas on how to improve it.

Ok, so I tried to plop this into mp3tag & it did nothing, so I’ve probably done something wrong as I have almost no understanding of regex

As per the MP3TAG documentation:
$regexp(x,e,r,c)

replaces the pattern specified by the regular expression e in the string x by r. The optional fourth parameter c enables ignore case (1) or disables the ignore case setting (0). Please note that you have to escape comma and other special characters in e.

In this case
x = %LYRICS%
e = The Regular Expression
r = The substitution? “$3($1)\n$4”
c = 1 or 0

I’m at a loss here lol instead of learning regex I opted to create massively convoluted simple scripting in MP3TAG to accomplish most of my actions.

I also popped over to Genius & did notice tracks with only one artist tend to just have one word within brackets as headers

[Chorus]

[Verse]

[Outro]

I’m not sure if that can our should be accounted for as well. For me if I’m including a header it will usually have artist(s) name(s) in it but I’m not sure what OP does in their lyrics.

Switching gears:
In this example here wouldn’t the “[Guitar Solo]” not be lost IF a timestamped lyric came before it? (At least in Symfonium)

Here lies some work I’m not necesarily proud of. I added only synced lyrics for the titles of the songs in this Live Performance (Tiny Desk Concert) for Leon Thomas. With this GENIUS formatting I’m able to click into my lyrics to jump to a specific part of his set. I was just far too lazy to sync each line. The lyrics are highlighted in gigantic blocks in the app but it worked so I shut my laptop for the day & sort of shoveled this monstrosity under the rug

[00:00.00]🅴 Score: •003•
[00:00.01] VIBES DON'T LIE
Vibes don't lie like the mouth do, do
[Verse 1]
Flowers die, and diamonds don't
You shouldn’t have to try alone
Tell me if you're mine or no
We like Wheezy and styrofoam
She got her own
Baby pushing G-Class, getting big figures
She can buy whatever, buy whatever but a real nigga

[Verse 2]
Real nigga give a fuck what it come out to
(hey)
It’s a difference over here
Arabian wood, smell me
She only drinks water
She keep that pussy healthy
It's the kind of bad thing that feel good, love it
Good thing that feel bad when you get too much of it
Way to live for a little, babe
I need more of it
Way too high for a little, babe
I'm sure of it

[Chorus] Repeated
Vibes don't lie

[Post-Chorus]
We don't gotta force it, know what time it is
We don’t trip about when the next time is
We don’t gotta force it, baby, just relax
Is what it is, let it just be that
Let it just be that
Let it just be that

[Refrain]
Vibes don't lie like the mouth do, do
[02:47.00] Chris Give em Some
[04:00.00] YES IT IS
When I'm talking to you, I don’t know what to say
But I can call up a stranger and talk my whole life away
Milwaukee margaritas
I didn't know that was a thing
Carry me home or marry me now
I promise you everything
Chanel in every city
Sitting pretty, talking dirty, whoa, whoa
Filthy mouth, filthy lips but my teeth pearly, oh I know
Bible scriptures on your left thigh
Verses you don't really live by
All she do is work, fuck, Uber Eats, and get high
Never will I fly you coach, babe
Never will I fly you coach maybe
Spend your summers on a boat, baby
I’m a vocal coach for your throat, babe, mmm
My ears are sensitive
Tell me that it's mine, oh

[Chorus]
All I hear is, "Yes, it is"
All I hear is, "Yes, it—, yes, it is", oh
My ears are sensitive
Tell me that it's mine, oh
All I hear is, "Yes, it is"
All I hear is, "Yes, it—, yes, it is"
My ears are sensitive
So when I ask you, "Is it mine?"
All you ever say is, "Yes, it is"

[Verse 2]
In Rene Caovilla, walking 'cross a tight rope
Bruises on her heart from jumping off boats
Gone for the weekend, yeah, that was the plan at first
Left on the 1st and it's already the 31st
Young, wild and free, I can't tame her
Young, wild and pretty in Miami, I can't blame her
She's a Virgo, so I can’t explain her
Tell me "Yes, it is"

[Chorus]
All I hear is, "Yes, it is"
All I hear is, "Yes, it—, yes, it is", oh
My ears are sensitive
Tell me that it’s mine, oh
All I hear is, "Yes, it is"
All I hear is, "Yes, it—, yes, it is"
My ears are sensitive
So when I ask you, "Is it mine?"
All you ever say is, "Yes, it is"

All you gotta do is say yes
Don't deny what you feel
Let me undress you baby, open up your mind just rest
I'm about to let you know, you make me so
so (repeated)

[Outro: Repeated]
Is it mine? Is it mine? Is it mine? Is it mine?
[08:11.00] MUTT
She said, "Take your time, what's the rush?"
I said, "Baby, I'm a dog, I'm a mutt"
She said, "Take your time, what's the rush?" Oh
I said, "Baby, I'm a dog, I'm a mutt"
I'm a dog, I'm a mutt

[Verse 1]
I can't smoke on reggie, so pardon my bluntness
I see past pretty faces, so I got trouble trusting

[Pre-Chorus]
But I'll let my guard down for you
Said I'll put my guard down for you
Said I'll be vulnerable
So you can break my heart if you want to

[Chorus]
She said, "Take your time, what's the rush?"
I said, "Baby, I'm a dog, I'm a mutt"
She said, "Take your time, what's the rush?"
I said, "Baby, I'm a dog, I'm a mutt"
I'm a dog, I'm a mutt

[Verse 2]
New crib, told her, "Come through," it's time to bring it in
Thirty-two, like my pants size 'cause a nigga tried breaking in
New condo, say your name at the front, you can stay if you want
It's been one of those nights, one of those nights I ain't had in a minute
It's been a minute, had to pop a shroom to recreate the feeling (Ooh, yeah)
But it's never the same as the first time we did it
First time we did it

[Pre-Chorus]
But I'll let my guard down for you (For you)
Said I'll put my guard down for you
Said I'll be vulnerable
So you can break my heart if you want to (Oh)

[Chorus]
She said, "Take your time, what's the rush?" (Take your time, what's the rush?)
I said, "Baby, I'm a dog, I'm a mutt" (Oh)
She said, "Take your time, what's the rush?" Oh (The rush)
I said, "Baby, I'm a dog, I'm a mutt" (Ooh)
I'm a dog, I'm a mutt (Mutt, oh)
[11:14.00] BREAKING POINT
Ooh, ooh
Ooh, ooh
Ooh, ooh

[Verse 1]
Slow dancin' in this burnin' house
I don't wanna go nowhere
It's hard for me to listen
When there's miles and miles of distance
Feel your heart is driftin' but you're right there
I call you home but I might be alone
Oh-oh-oh, I can hear it in your tone, we're in the danger zone
In the danger zone, yeah

[Bridge]
Way past the breakin' point
'Cause I can't turn down the noise
You are my only choice
And we're both just fillin' voids
Way past the breakin' point
'Cause I can't turn down the noise
You are my only choice
We're both just fillin' voids

[Pre-Chorus]
Breakin' point
Breakin' point
Oh, oh-oh-oh

[Chorus]
They told me love was fragile
They told me love was breakable
I thought that I could handle
But that is still debatable
I thought that this was for me
But it's feelin' impossible
Breakin' point, breakin' point

[Post-Chorus]
Oh-oh-oh, oh-oh
Oh, oh-oh-oh, oh, hey, hey, hey
Breakin' point, breakin' point
[15:40.00] TREASURE IN THE HILLS
Play by the rules
But l'd rather do something naughty
Let's find a room, woah
Inside this after party

[Refrain]
Been on a hunt, found what I want
Found what I want in you

[Chorus]
I found treasure in the hills
I found treasure in the hills
I found treasure in the hills
I found treasure in the hills
Chase more than diamonds and gold
I'm trying to find me a soul
Chase more than diamonds and gold
I'm trying to find me a soul

[Verse 2]
You live alone
Now it's just you and your shadow
Let's change that up
Let's take it into tomorrow

[Refrain]
Been on a hunt, found what I want
Found what I want in you

[Chorus]
I found treasure in the hills
I found treasure in the hills
I found treasure in the hills
I found treasure in the hills
Chase more than diamonds and gold
I'm trying to find me a soul
Chase more than diamonds and gold
I'm trying to find me a soul

[Outro]
Cheering

For Mp3tag you have to do some extra escaping when you use regular expressions in actions/scripting. Since Mp3tag regex doesn’t seem to support multi-line flags, I had to adjust the regex quite a bit by making some things non-greedy etc. but this works for my example:

$regexp(%LYRICS%,\'['((?!(ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\']')'['^\n']'*?)\']'\n(\'['\d{1,2}:\d{1,2}\.\d{2,3}\']')('['^\n']'*),$3($1)\n$4)

The only thing that’s ignored are the specific lrc tags I’ve taken from the wikipedia page. What’s in the genius headers should not matter unless it happens to match one of the tags or the syntax of the start of a timestamp line exactly. That ought to be relatively unlikely tho.

You might want to change the square brackets to round ones as well to avoid that, yes.
I usually denote instrumental passages by an empty line with a timestamp like this:

[03:23.713]Da nahm der Wicht sein Denken
[03:26.878]und schenkte es den Wellen,
[03:30.149]die Meere nahmen es auf.
[03:34.955]
[05:37.305]Das Denken fand man bis heute nicht...
[05:40.999]...bis heute nicht
[05:43.608]bis heute nicht

At that point it would probably have been just as much work to split the file into individual songs, but it’s an interesting usage of synced lyrics.

This means that:

[00:03.05] (Verse 1: James Car)
[00:03.05] We Lift our Hands

and

[00:03.05] (Verse 1: James Car)
We Lift our Hands

would be displayed identically in Symfonium. In this case I think this action would be better as it retains the timestamp in front of the line it belongs to and only prepends the same timestamp to the header while exchanging the square brackets with round ones.

$regexp(%LYRICS%,\'['((?!(ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\']')'['^\n']'*?)\']'\n(\'['\d{1,2}:\d{1,2}\.\d{2,3}\']')('['^\n']'*),$3($1)\n$3$4)

Two reasons:

  1. Programs that do not support multi-line lyrics should still display the actual line and not only the header.
  2. It’s far easier to reverse in case that the parsing in Symfonium is changed down the line.

Edit: If the action does not work on your lyrics you probably use a different end of line character and could have more luck with this version:

$regexp(%LYRICS%,\'['((?!(ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\']')'['^\n']'*?)\']'\r\n(\'['\d{1,2}:\d{1,2}\.\d{2,3}\']')('['^\n']'*),$3($1)\r\n$3$4)
1 Like

For me this is producing a carbon copy in MP3TAG

LYRICS at the top is what I started with & when using your regex to format the value of UNSYNCEDLYRICS at the bottom it’s the same.

EDIT:
The above regex from @655321 does work for standard synced lyrics with these “headers”. My lyrics just have extra line breaks in them.

Did you use it in an action or in a converter? ̶I̶ ̶t̶h̶i̶n̶k̶ ̶t̶h̶e̶r̶e̶ ̶m̶i̶g̶h̶t̶ ̶b̶e̶ ̶d̶i̶f̶f̶e̶r̶e̶n̶t̶ ̶e̶s̶c̶a̶p̶i̶n̶g̶ ̶n̶e̶e̶d̶s̶ ̶d̶e̶p̶e̶n̶d̶i̶n̶g̶ ̶o̶n̶ ̶t̶h̶a̶t̶.̶
I’ve tested the regex in a Tag → Tag converter where it works. A carbon copy means that no match was found.

The Preview is especially useful to test regexes before applying them.

Anyhow as this is not the Mp3tag forum, I think we should take this to DMs if you have further questions.

Edit:
It also works for me as a Format Value action:

1 Like

Thanks for trying yall. I really hope this can get fixed. Its kinda the only thing bugging me rn even though I would gladly make the change from musicolet to symfonium :slight_smile:

As of now if you use either of these REGEX strings from @655321 in MP3TAG you can alter your current lyrics across your entire library so that they will work in Symfonium just as they did is musicolet.

Cool part is your lyrics should also work with other applications as well as they contain timestamps for all the lines you want shown.

I was able to use this successfully in my library on a few tracks already

And yet you still have not provided the asked file to know exactly what you are doing :wink:

Idk if ur talking abt me or nah but i just Uploaded a track. Its just really random basic synced lyrics with brackets that have no time stamps.
I didn’t expect finding a solution would be this complicated. I thought u could just code it in a way that if a bracket has no timestamp it just gets treated like a normal text

There’s many explanations about why this is not that simple when you fully embrace all LRC supports like the tags and the multiple time stamps.

Adding a couple of kown tags in those lyrics will make Musicolet show everything after the first one it does not recognize.

Musicolet does not understand the lr value in the LRC tags and it makes it ignore all the tags after leading to this.

As you can see this is ugly and wrong, and since the list of tags is not 100% defined this cause a problem with the way Genius works since [Into: Vory] is actually a valid way to describe a tag in lrc is never to be shown.

So if we respect LRC the [Intro: Vory] Should never be displayed since it’s a valid tag before any synced data.

So this is not a coding issue, this is a problem of wanting something that is not supposed to work the way it’s supposed to work.

Anything would have side effects, the best solutions are to fix the lyrics and the other users have done all the work to allow you to do that easily.

1 Like

With a fresh head I’ve prettied up the Mp3tag regex to this:

$regexp(%LYRICS%,\'['(?<header>(?!(?:ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\']')'['^\r\n']'+?)\']'(?<newline>\r?\n)(?<timestamp>\'['\d{1,2}:\d{1,2}\.\d{2,3}\']')(?<lrcline>'['^\r\n']'*),$+{timestamp}($+{header})$+{newline}$+{timestamp}$+{lrcline})

It’s longer but with named capturing groups it should be easier to follow what it does. This version also handles both cases of \r\n (CR LF) and only \n (LF) as end of line characters.

Assuming that the synced lyrics are stored in the tag LYRICS, this action would alter them in-place:

Action type: Format value
Field:

LYRICS

Format string:

$regexp(%LYRICS%,\'['(?<header>(?!(?:ti|ar|al|au|lr|length|by|offset|re|tool|ve|#|\d{1,2}):.*\']')'['^\r\n']'+?)\']'(?<newline>\r?\n)(?<timestamp>\'['\d{1,2}:\d{1,2}\.\d{2,3}\']')(?<lrcline>'['^\r\n']'*),$+{timestamp}($+{header})$+{newline}$+{timestamp}$+{lrcline})

Let me know if it changes something it should not. I’ve also posted this workaround in the Mp3tag forum.

1 Like