It is currently September 9th, 2024, 10:46 am

[Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Report bugs with the Rainmeter application and suggest features.
Rhyuno
Posts: 17
Joined: August 4th, 2024, 6:30 am

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Rhyuno »

Yincognito wrote: August 6th, 2024, 8:19 pm So, are you still interested in this? You know, to not work on it pointlessly. I've been a bit busy the last few days so I didn't get the time to finish the sample, but if you want, I could - I didn't forget about it, and it's not a problem. ;-)
Yes, I'm still very interested in this. I've been a bit busy lately since I'm still attending college. I actually thought about it and tried to program this, but I've had trouble using RegExp to get the timestamp in the [MeasureGetSyncedLyrics]. I used RegExp="(\[\d{1,2}:\d{2}(?:\.\d{1,2})?\])", but it's only retrieving one timestamp. My plan was to retrieve all the timestamps and put them in a .txt file that updates and changes every time the song changes.

Huge thanks for the references you gave me; I understood the logic with IfMatchActions. I'm planning to use the .txt file with all the timestamps and match it with [MeasurePosition], changing the Y value to scroll the lyrics.

I've realized a significant flaw in this method: it's not connected with [MeasureProgress]. This means that if this method works and I try skipping to a specific timestamp in the song, the lyrics won't sync with the song. But that will be a problem for another day.

I went with the RegExp Substitute / IfMatch method, as I'm not really familiar with or have any experience in programming in Lua. I really appreciate all the help I'm receiving on this one. :D
User avatar
Yincognito
Rainmeter Sage
Posts: 8049
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Yincognito »

Rhyuno wrote: August 7th, 2024, 4:18 pm Yes, I'm still very interested in this. I've been a bit busy lately since I'm still attending college. I actually thought about it and tried to program this, but I've had trouble using RegExp to get the timestamp in the [MeasureGetSyncedLyrics]. I used RegExp="(\[\d{1,2}:\d{2}(?:\.\d{1,2})?\])", but it's only retrieving one timestamp. My plan was to retrieve all the timestamps and put them in a .txt file that updates and changes every time the song changes.

Huge thanks for the references you gave me; I understood the logic with IfMatchActions. I'm planning to use the .txt file with all the timestamps and match it with [MeasurePosition], changing the Y value to scroll the lyrics.

I've realized a significant flaw in this method: it's not connected with [MeasureProgress]. This means that if this method works and I try skipping to a specific timestamp in the song, the lyrics won't sync with the song. But that will be a problem for another day.

I went with the RegExp Substitute / IfMatch method, as I'm not really familiar with or have any experience in programming in Lua. I really appreciate all the help I'm receiving on this one. :D
Alright, no worries, take your time and don't neglect "real life" as the skin is no urgency. Yes, the path you took is exactly right, well done! :thumbup:

In the end, Lua won't be necessary and the whole thing really isn't that hard to achieve (you could indeed do everything with regexes). You can (RegExp) Substitute the needed line parts with "+1" in some String measure duplicates of the lyrics measure, followed by using Calc measures with the said String measures in their Formula options, to compute how many lines the lyrics has in total and how many lines there are until the currently played line. Then, you could scroll and change the Y of the lyrics meter based on the currently played line. This is because you can find the line height by dividing the lyrics text meter's height (i.e. [MeterLyrics:H]) by the number of total lines in the lyrics and you can modify the Y by adding or subtracting a product of line height and the number of lines until the currently played line.

Also, you don't need all the timestamps or to save them anywhere in this approach - for both scrolling like above and highlighting the currently played line, you only need to find where the currently played line is in the lyrics string. For example, I already do karaoke highlighting in the sample skin I wrote, by using inline settings in a meter similar to this (I left only the relevant parts for clarity and used the names from the skin you linked to, to better get the idea; by the way, I only used the character variable for [ because using the literal seems to cause problems when used from a !SetOption bang since it's right near the [section] markers):

Code: Select all

[MeterLyrics]
...
Meter=String
...
X=...
Y=...
W=...
InlineSetting=Color | 255,0,0,255
InlinePattern=(?siU)\[\x005B][MeasurePosition].*\R
MeasureName=MeasureGetSyncedLyrics
Text=%1
DynamicVariables=1
Synced Lyrics Karaoke Highlighting.jpg
Regarding [MeasureProgress], I don't think it's a flaw. In the NowPlaying plugin which I use with Winamp (and probably in WebNowPlaying too, though I don't use it that often), [MeasureProgress] is precisely [MeasurePosition]/[MeasureDuration]*100. Not sure about Spotify, since one has to perform some "tricks" to make it work properly with WebNowPlaying (user xenium knows those things best).
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Rhyuno
Posts: 17
Joined: August 4th, 2024, 6:30 am

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Rhyuno »

Yincognito wrote: August 7th, 2024, 6:57 pm Alright, no worries, take your time and don't neglect "real life" as the skin is no urgency. Yes, the path you took is exactly right, well done! :thumbup:

In the end, Lua won't be necessary and the whole thing really isn't that hard to achieve (you could indeed do everything with regexes). You can (RegExp) Substitute the needed line parts with "+1" in some String measure duplicates of the lyrics measure, followed by using Calc measures with the said String measures in their Formula options, to compute how many lines the lyrics has in total and how many lines there are until the currently played line. Then, you could scroll and change the Y of the lyrics meter based on the currently played line. This is because you can find the line height by dividing the lyrics text meter's height (i.e. [MeterLyrics:H]) by the number of total lines in the lyrics and you can modify the Y by adding or subtracting a product of line height and the number of lines until the currently played line.

Also, you don't need all the timestamps or to save them anywhere in this approach - for both scrolling like above and highlighting the currently played line, you only need to find where the currently played line is in the lyrics string. For example, I already do karaoke highlighting in the sample skin I wrote, by using inline settings in a meter similar to this (I left only the relevant parts for clarity and used the names from the skin you linked to, to better get the idea; by the way, I only used the character variable for [ because using the literal seems to cause problems when used from a !SetOption bang since it's right near the [section] markers):

Code: Select all

[MeterLyrics]
...
Meter=String
...
X=...
Y=...
W=...
InlineSetting=Color | 255,0,0,255
InlinePattern=(?siU)\[\x005B][MeasurePosition].*\R
MeasureName=MeasureGetSyncedLyrics
Text=%1
DynamicVariables=1
This is a bit embarrassing to admit, and I don't mean to be a downer, but I feel like I don't know what I'm doing anymore (which, as a coder, happens to me a lot). I've tried every tip, but I feel like I'm not making any progress. I'm not sure if this is correct, but here's what my current code looks like. Feel free to edit anything. :???:
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 8049
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Yincognito »

Rhyuno wrote: August 8th, 2024, 12:11 pm This is a bit embarrassing to admit, and I don't mean to be a downer, but I feel like I don't know what I'm doing anymore (which, as a coder, happens to me a lot). I've tried every tip, but I feel like I'm not making any progress. I'm not sure if this is correct, but here's what my current code looks like. Feel free to edit anything. :???:
Don't worry, it's ok, it happens to everyone once in a while. Yeah, you mostly did well, apart from the Substitute options in [MeasureTotalLines] and [MeasureCurrentLine].

For example, the first one of these measures should look something like (notice the presence of RegExpSubstitute=1, to enable regex in the following Substitute option):

Code: Select all

[MeasureTotalLines]
Measure=String
String=[MeasureLyrics]
RegExpSubstitute=1
Substitute="\N*(?:\R|$)":"+1"
DynamicVariables=1
In the substitute, \N is any char that's not a newline one, \R is a newline char (either \r\n or just \n, as you probably know already), and $ is the end of the string. So basically we're replacing each line with "+1" in order to compute the resulting sum in [MeasureCountTotalLines].

For the [MeasureCurrentLine], you'll have to apply the same idea, except that before you replace lines with "+1" you'll have to 'trim' the string to include only the part between the start of the string and the currently played line (something like "(?siU)^(.*)\[\x005B][MeasurePosition].*\R.*$":"\1", but further refinements will have to be made to account for the possibility of not having the current track position in the lyrics string, and the fact that Rainmeter replaces the empty captures with the literal \1, \2 and so on as the note here explains).

Once you do the above (start with the total lines first, as it's simpler), you should get some meaningful results in the corresponding Calc measures and fill the blanks bit by bit (watch the About > Skins tab's values for your measures). ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 8049
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Yincognito »

Yincognito wrote: August 4th, 2024, 7:53 pm I may take a deeper look at this [...] and maybe come up with a rudimentar sample code
Rhyuno wrote: August 7th, 2024, 4:18 pm Yes, I'm still very interested in this. [...] I really appreciate all the help I'm receiving on this one. :D
Alright, as promised, here's the - not yet fully polished - sample that demonstrates displaying the synced lyrics, the automatic (when playing) and manual (when stopped or paused) scrolling, as well as the karaoke highlighting of the currently played lyrics line:

Code: Select all

[Variables]
BackgroundW=400
BackgroundH=600
StrokeWidth=2
CornerRadius=10
Margin=10
BackgroundColor=0,0,0,128
StrokeColor=255,128,0,255
InfoColor0=255,128,128,255
InfoColor1=128,128,255,255
InfoColor2=128,255,128,255
InfoColor3=255,128,255,255
ControlColor0=255,255,128,255
ControlColor1=128,255,255,255
ControlColor2=128,255,255,255
ControlColor3=255,255,128,255
LyricsColor=192,192,192,255
KaraokeColor=255,255,255,255
FontEffectColor=0,0,0,255
FontColor=255,255,255,255
FontFace=Monotype Corsiva
FontSize=16
StringEffect=Shadow
FontPerc=0.75
BarHPerc=0.80
BarSolid=128,128,128,255
BarColor=0,255,0,255
ControlNum=4
ControlGap=50
Prev=[\x23EE]
Stop=[\x23F9]
Play=[\x23F5]
Next=[\x23ED]
Pause=[\x23F8]
BoxColor=0,0,0,128
Player=Winamp
Offset=0
LineH=0
Lines=0
Line=0

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1

---Measures---

[Status]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=#Player#
PlayerType=Status
RegExpSubstitute=1
Substitute="^0$":"Closed","^1$":"Open"
TrackChangeAction=[!SetVariable Offset 0][!CommandMeasure SyncedLyrics "Update"]

[State]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=State
RegExpSubstitute=1
Substitute="^0$":"Stopped","^1$":"Playing","^2$":"Paused"
IfCondition=(State=1)
IfTrueAction=[!SetOption Play Text "#Pause#"]
IfFalseAction=[!SetOption Play Text "#Play#"]

[Artist]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Artist
RegExpSubstitute=1
Substitute="^$":"No Artist"

[Album]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Album
RegExpSubstitute=1
Substitute="^$":"No Album"

[Title]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Title
RegExpSubstitute=1
Substitute="^$":"No Title"

[Duration]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Duration

[Position]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Position
OnChangeAction=[!UpdateMeasureGroup LinesGroup]

[Progress]
Group=PlayerGroup
Measure=NowPlaying
PlayerName=[Status]
PlayerType=Progress

[SyncedLyrics]
Measure=WebParser
;URL=file://#@#Madonna - Material Girl (original).json
;URL=file://#@#Eminem - My Name Is (original).json
URL=https://lrclib.net/api/get?artist_name=[&Artist]&album_name=[&Album]&track_name=[&Title]&duration=[&Duration:]
UserAgent=Rainmeter 4.5.18 (https://github.com/rainmeter)
RegExp=(?siU)[{,]"syncedLyrics":"(.*)"[,}]
StringIndex=1
;Debug=2
UpdateRate=-1
RegExpSubstitute=1
Substitute='(?sU)\\"':'"',"(?sU)\\n":"#CRLF#"
FinishAction=[!UpdateMeasureGroup LinesGroup]
IfMatch=(?siU)\[\x005B][Position].+\R
IfMatchAction=[!SetOption LyricsText "InlineSetting" "Color | #KaraokeColor#"][!SetOption LyricsText "InlinePattern" "(?siU)\[\x005B][Position].+\R"]
;IfNotMatchAction=[]
IfMatchMode=1
DynamicVariables=1

[Lines]
Group=LinesGroup
Measure=String
String=[SyncedLyrics]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="(?siU).+(?:\R|$)":"+1","(?siU)^(.*)$":"0\1","\\\d+":""
OnUpdateAction=[!SetVariable Lines ([Lines])][!SetVariable LineH ([LyricsText:H]/([#Lines]=0?1:[#Lines]))]
DynamicVariables=1

[Line]
Group=LinesGroup
Measure=String
String=[SyncedLyrics]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="(?siU)^(?|(.*)\[\x005B][Position].+(?:\R|$).*|((?:.+(?:\R|$)){#Line#}).*)$":"\1","\\\d+":"","(?siU).+(?:\R|$)":"+1","(?siU)^(.*)$":"0\1","\\\d+":""
OnUpdateAction=[!SetVariable Line ([Position:]=0?0:[Line])][!SetVariable Offset ([#LineH]*[#Line])][!UpdateMeter *][!Redraw]
DynamicVariables=1

---Styles---

[Texts]
FontEffectColor=#FontEffectColor#
FontColor=#FontColor#
FontFace=#FontFace#
FontSize=#FontSize#
AntiAlias=1
StringEffect=#StringEffect#

---Meter---

[Background]
Meter=Shape
Shape=Rectangle (#StrokeWidth#/2),(#StrokeWidth#/2),(#BackgroundW#-#StrokeWidth#),(#BackgroundH#-#StrokeWidth#),(#CornerRadius#),(#CornerRadius#) | Fill Color #BackgroundColor# | Stroke Color #StrokeColor# | StrokeWidth #StrokeWidth#
UpdateDivider=-1

[Information]
Meter=String
MeterStyle=Texts
StringAlign=Center
X=(#BackgroundW#/2)
Y=(#Margin#)
W=(#BackgroundW#-#Margin#*2)
InlineSetting=Color | #InfoColor0#
InlinePattern=^(?:\N*\R){0}(\N*)
InlineSetting2=Color | #InfoColor1#
InlinePattern2=^(?:\N*\R){1}(\N*)
InlineSetting3=Color | #InfoColor2#
InlinePattern3=^(?:\N*\R){2}(\N*)
InlineSetting4=Color | #InfoColor3#
InlinePattern4=^(?:\N*\R){3}(\N*)
MeasureName=Artist
MeasureName2=Album
MeasureName3=Title
MeasureName4=Duration
MeasureName5=Position
MeasureName6=Progress
MeasureName7=Status
MeasureName8=State
Text=%1#CRLF#%2#CRLF#%3#CRLF#%5 of %4 (%6%) - Player is %7 & %8
DynamicVariables=1

[ProgressBar]
Meter=Bar
MeasureName=Progress
X=(#Margin#)
Y=(#Margin#/2)R
W=(#BackgroundW#-#Margin#*2)
H=(#FontSize#*#BarHPerc#)
BarColor=#BarColor#
SolidColor=#BarSolid#
BarOrientation=Horizontal
LeftMouseDownAction=[!CommandMeasure Progress "SetPosition $MouseX:%$"][!UpdateMeasureGroup PlayerGroup][!UpdateMeter *][!Redraw]
DynamicVariables=1

[Prev]
Meter=String
MeterStyle=Texts
X=(#BackgroundW#/2-#ControlGap#/2*(#ControlNum#-1))
Y=(#Margin#/2)R
StringAlign=Center
FontColor=#ControlColor0#
Text=#Prev#
LeftMouseUpAction=[!CommandMeasure Status "Previous"][!UpdateMeasureGroup PlayerGroup][!UpdateMeter *][!Redraw]

[Stop]
Meter=String
MeterStyle=Texts
X=(#ControlGap#)r
Y=(0)r
StringAlign=Center
FontColor=#ControlColor1#
Text=#Stop#
LeftMouseUpAction=[!CommandMeasure Status "Stop"][!UpdateMeasureGroup PlayerGroup][!UpdateMeter *][!Redraw]

[Play]
Meter=String
MeterStyle=Texts
X=(#ControlGap#)r
Y=(0)r
StringAlign=Center
FontColor=#ControlColor2#
Text=#Play#
LeftMouseUpAction=[!CommandMeasure Status "PlayPause"][!UpdateMeasureGroup PlayerGroup][!UpdateMeter *][!Redraw]

[Next]
Meter=String
MeterStyle=Texts
X=(#ControlGap#)r
Y=(0)r
StringAlign=Center
FontColor=#ControlColor3#
Text=#Next#
LeftMouseUpAction=[!CommandMeasure Status "Next"][!UpdateMeasureGroup PlayerGroup][!UpdateMeter *][!Redraw]

[LyricsBox]
Meter=Image
X=(#Margin#)
Y=(#Margin#/2)R
W=(#BackgroundW#-#Margin#*2)
H=(#BackgroundH#-[LyricsBox:Y]-#Margin#)
SolidColor=#BoxColor#
UpdateDivider=-1
DynamicVariables=1

[LyricsContainer]
Meter=Image
X=([LyricsBox:X])
Y=([LyricsBox:Y])
W=([LyricsBox:W])
H=([LyricsBox:H])
SolidColor=0,0,0,255
UpdateDivider=-1
MouseScrollUpAction=[!SetVariable Offset (Clamp(#Offset#-#LineH#,0,Clamp([LyricsText:H]-[LyricsContainer:H],0,[LyricsText:H])))][!UpdateMeter LyricsContainer][!UpdateMeter LyricsText][!Redraw]
MouseScrollDownAction=[!SetVariable Offset (Clamp(#Offset#+#LineH#,0,Clamp([LyricsText:H]-[LyricsContainer:H],0,[LyricsText:H])))][!UpdateMeter LyricsContainer][!UpdateMeter LyricsText][!Redraw]
DynamicVariables=1

[LyricsText]
Container=LyricsContainer
Meter=String
MeterStyle=Texts
StringAlign=Center
FontColor=#LyricsColor#
FontSize=(#FontSize#*#FontPerc#)
X=([LyricsBox:W]/2)
Y=(-Clamp(#Offset#,0,Clamp([LyricsText:H]-[LyricsContainer:H],0,[LyricsText:H])))
W=([LyricsBox:W])
MeasureName=SyncedLyrics
Text=%1
DynamicVariables=1
Desktop_2024_08_08_20_32_42_103-ezgif.com-optimize.gif
It almost certainly has a few "bugs" or things I didn't bother to make perfect, but it's enough to get the general idea. It uses NowPlaying (not WebNowPlaying!) as the plugin and Winamp (not Spotify!) as the player, since that's what I use and could test, so it's entirely up to you - or anyone interested - to adapt it to another plugin or less supported player. In some areas, this might be a little challenge, for example replicating the TrackChangeAction option in NowPlaying, which WebNowPlaying doesn't yet have (here, concatenating the artist, track and duration in a String measure and comparing the outcome with the previous outcome of the same measure that was stored in a variable during the previous update of the measure could be one way to do it, besides using an OnChangeAction on that measure).

Regarding the commented lines from the code:
- I used the Debug=2 option in the [SyncedLyrics] measure to save the site's response on two test tracks, renamed and moved the file(s) accordingly, and parsed them as local files in the URL option in order to avoid excessively polling the site during the building and testing phase of the skin (this is wise to do both as a general rule when working with WebParser and also whenever working with sites that might block or ban you for using them too frequently)
- the IfNotMatchAction is left in case you want to do something else when the currently played line is not found in the lyrics text, since in this implementation both the scrolling (the ((?:.+(?:\R|$)){#Line#}).* part in the branch reset from [Line]) and the highlighting (the IfMatchAction) intentionally stay on the last #Line# value until another [Position] value is found in the lyrics string; this is done because otherwise (like the highlighting variant from the code here) the highlight will only stay on the currently played line for the duration of one [Position] update, i.e. just one second, which might not be enough time if the lyrics line is or lasts longer (it sometimes is inconvenient though, like when stopping the current track)

Obviously, you don't have to use this sample going forward, you could just add the needed things from it to the Mjdelro skin you're using. I do recommend testing stuff in this sample first though, simply because it's easier and it already works. Yes, you can use measures (like the [MeasureCountTotalLines], [MeasureCountCurrentLine] or [MeasureLineHeight] in the code from your previous reply) instead of variables (like the #Lines#, #Line# or #LineH# in the code from this sample) to store the said numerical values, I only used the latter cause it's more compact and takes less space in the code (I like one measure solutions). ;-)

Feel free to ask if you don't understand something - although judging by the quite correct way you already started to implement stuff in the past replies, I'm pretty sure you won't have many problems (besides occasional obstacles due to less Rainmeter experience) getting the principles in this code.

P.S. In case it's not obvious, the above system of scrolling (the karaoke highlighting is not affected) will not work properly if you set the lyrics text to potentially wrap longer lines, because in that case, the height of a "line" will vary depending on whether it's wrapped or not, while its computation assumes that line height value is always constant and equal to the height of an unwrapped line. There are probably solutions that would allow wrapping too, but in the interest of simplicity I didn't cover that above. One way to not need wrapping would be to allow horizontal scrolling too, along with the already existing vertical one.
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Rhyuno
Posts: 17
Joined: August 4th, 2024, 6:30 am

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Rhyuno »

Yincognito wrote: August 8th, 2024, 7:22 pm Alright, as promised, here's the - not yet fully polished - sample that demonstrates displaying the synced lyrics, the automatic (when playing) and manual (when stopped or paused) scrolling, as well as the karaoke highlighting of the currently played lyrics line: [...]

P.S. In case it's not obvious, the above system of scrolling (the karaoke highlighting is not affected) will not work properly if you set the lyrics text to potentially wrap longer lines, because in that case, the height of a "line" will vary depending on whether it's wrapped or not, while its computation assumes that line height value is always constant and equal to the height of an unwrapped line. There are probably solutions that would allow wrapping too, but in the interest of simplicity I didn't cover that above. One way to not need wrapping would be to allow horizontal scrolling too, along with the already existing vertical one.
Wow, I just got out of university. Thanks for this sample code—this is exactly what I've been looking for in a lyrics skin! I just tried it for a bit and changed the measures to Measure = Plugin and set the plugin to Plugin = WebNowPlaying to make it work with Spotify.

I haven't thoroughly examined the program yet, but it seems like I'm having some trouble with auto-scrolling the lyrics by line and highlighting them. It's not working as it did in the GIF you sent.

However, I can see that things might get easier from here on out. Regarding the TrackChangeAction, I think Simple Lyrics Display used OnUpdateAction or OnChangeAction, so I'll try those out as well.

I'll use this sample as a foundation and make further changes using it. 8-)
User avatar
Yincognito
Rainmeter Sage
Posts: 8049
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Yincognito »

Rhyuno wrote: August 9th, 2024, 10:48 am Wow, I just got out of university. Thanks for this sample code—this is exactly what I've been looking for in a lyrics skin! I just tried it for a bit and changed the measures to Measure = Plugin and set the plugin to Plugin = WebNowPlaying to make it work with Spotify.

[...]

However, I can see that things might get easier from here on out. Regarding the TrackChangeAction, I think Simple Lyrics Display used OnUpdateAction or OnChangeAction, so I'll try those out as well.

I'll use this sample as a foundation and make further changes using it. 8-)
Sure thing, you're welcome! :great:
Rhyuno wrote: August 9th, 2024, 10:48 amI haven't thoroughly examined the program yet, but it seems like I'm having some trouble with auto-scrolling the lyrics by line and highlighting them. It's not working as it did in the GIF you sent.
That's why I said to first try the sample in its unchanged form, with NowPlaying and a fully supported player like Winamp and such (and on some tracks that you know for sure that their lyrics perfectly match what is returned by the site), so you can see how it works and what to expect, before adapting it to your scenario. Don't try to do it all at once, just take it step by step and things will probably fare better. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Rhyuno
Posts: 17
Joined: August 4th, 2024, 6:30 am

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Rhyuno »

Yincognito wrote: August 9th, 2024, 12:18 pm That's why I said to first try the sample in its unchanged form, with NowPlaying and a fully supported player like Winamp and such (and on some tracks that you know for sure that their lyrics perfectly match what is returned by the site), so you can see how it works and what to expect, before adapting it to your scenario. Don't try to do it all at once, just take it step by step and things will probably fare better. ;-)
Update:

Since we don't have any classes during the weekends, I've started working on this skin. I discovered that Spotify provides inaccurate time positions compared to Winamp and doesn't support the timestamp format of LRC files. I spent some time studying a bit of Lua and created a custom timer that matches the timestamp format of LRC files. It uses [Rainmeter] Update = 16 to provide accurate milliseconds, and now the lyrics are highlighting the currently played lines as they should.

Currently, I'm working on figuring out the "tricks" with TrackChangeAction, as the timer isn't restarting when the track changes.
User avatar
Yincognito
Rainmeter Sage
Posts: 8049
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Yincognito »

Rhyuno wrote: August 10th, 2024, 10:12 am Update:

Since we don't have any classes during the weekends, I've started working on this skin. I discovered that Spotify provides inaccurate time positions compared to Winamp and doesn't support the timestamp format of LRC files. I spent some time studying a bit of Lua and created a custom timer that matches the timestamp format of LRC files. It uses [Rainmeter] Update = 16 to provide accurate milliseconds, and now the lyrics are highlighting the currently played lines as they should.

Currently, I'm working on figuring out the "tricks" with TrackChangeAction, as the timer isn't restarting when the track changes.
Nicely done! :thumbup:

Just curious though, what do you mean by "doesn't support the timestamp format of LRC files"? You mean that WebNowPlaying / NowPlaying don't provide the milliseconds, or you refer to WebNowPlaying providing the position as plain seconds (e.g. 241) instead of minutes:seconds (e.g. 04:01)?

Anyway, yeah, if you want better precision, Lua can do that indeed, although Rainmeter can do stuff under the 16 ms interval too, through the ActionTimer plugin:
https://docs.rainmeter.net/manual/plugins/actiontimer/

I used only plain Rainmeter above for simplicity, though if you want to refine things, Lua can definitely help with that.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Rhyuno
Posts: 17
Joined: August 4th, 2024, 6:30 am

Re: [Friendly Resource] If PlayerType=Lyrics needs an update, LRCLIB can be used

Post by Rhyuno »

Yincognito wrote: August 10th, 2024, 12:44 pm Nicely done! :thumbup:
Thanks! :D
Just curious though, what do you mean by "doesn't support the timestamp format of LRC files"? You mean that WebNowPlaying / NowPlaying don't provide the milliseconds?
That's exactly right. I'm not entirely sure which part is causing it, but based on my research, Spotify only provides time in the mm:ss format. Because of this, I had to create a custom timer in the mm:ss.xx format that syncs with Spotify's mm:ss format to approximately sync the lyrics. I think this could be a pretty universal solution across any music player.

As of now, I'm still working on finding a substitute method for TrackChangeAction. I'm also having problems whenever I skip in the music, as the timer I've created so far doesn't support such action.