sentriz / gonic

music streaming server / free-software subsonic server API implementation
ircs://irc.libera.chat/#gonic
GNU General Public License v3.0
1.62k stars 115 forks source link

`.lrc` lyrics? #371

Open duckfromdiscord opened 1 year ago

duckfromdiscord commented 1 year ago

I've noticed the Subsonic protocol supports lyrics. I have a couple .lrc files lying around that I'd like to add to gonic to complete my music collection, especially with certain streaming services considering paywalling lyrics. My suggestion is to have the .lrc file have the same name as the audio file, minus its extension and plus .lrc. An example using the folder structure in the README:

music
├── drum and bass
│   └── Photek
│       └── (1997) Modus Operandi
│           ├── 01.10 The Hidden Camera.flac
│           ├── 01.10 The Hidden Camera.lrc
│           ├── 02.10 Smoke Rings.flac
│           ├── 02.10 Smoke Rings.lrc
│           ├── 03.10 Minotaur.flac
│           ├── 03.10 Minotaur.lrc
│           └── folder.jpg

The .lrc format is super easy to deal with, it's just plaintext with timestamps. There are some optional tags at the beginning of lyric files, check out the Wikipedia page for a good list.

[00:01.099]Hello world
sentriz commented 1 year ago

are there any subsonic clients that support lyrics?

duckfromdiscord commented 1 year ago

are there any subsonic clients that support lyrics?

I use iSub and it has a lyrics window, that's how I found out about it.

I wish Subsonic had a time-synced lyrics thing as well so I could truly push those .lrc files to their limits, but that's a question for Subsonic, not this repo 😂

dweymouth commented 1 year ago

are there any subsonic clients that support lyrics?

I am planning on adding it to Supersonic in the near- to mid-future. Feishin (Sonixd's successor) supports lyrics but not the Subsonic API yet, I think it's waiting for OpenSubsonic

Tolriq commented 1 year ago

Just seeing this, Symfonium support them too, We need to extend OpenSubsonic API to support songId to getLyrics to have this properly added to Subsonic. Will make the API request later.

Tolriq commented 1 year ago

https://github.com/opensubsonic/open-subsonic-api/pull/58

duckfromdiscord commented 1 year ago

This OpenSubsonic thing is cool! I wonder if I could ask about timed lyrics there.

Tolriq commented 1 year ago

The lyrics are returned as is, so if they have the offsets they will be synced on the clients if they support it.

duckfromdiscord commented 1 year ago

Perhaps the timings like [00:00.00] should be removed by the server if the lyrics are being sent to a client that doesn't support them

duckfromdiscord commented 1 year ago

I could go through each of my .lrc files with a regex that removes them, and output them as .txt files, seeing as my client obviously doesn't support the timings anyway.

dweymouth commented 1 year ago

OpenSubsonic RfC for lyrics API improvements is up https://github.com/opensubsonic/open-subsonic-api/discussions/60

duckfromdiscord commented 1 year ago

This is amazing news!

TorchedSammy commented 11 months ago

I see the lyrics API has the label "In production" which means this can be worked on now?

duckfromdiscord commented 11 months ago

Is there a .lrc parser for Go?

duckfromdiscord commented 11 months ago

https://pkg.go.dev/github.com/env25/mpdlrc/lrc could work!

bytebone commented 9 months ago

while I'm in no way proficient with go, I might just know enough to attempt an implementation on this. Maybe someone more experienced can provide me with some rough pointers where one should start with this, what things to consider? Then I could try getting my hands dirty.

duckfromdiscord commented 9 months ago

We're in the same boat. I have no experience with Go, I'm better with Rust. I do know that you should use a lrc parsing library like the one I posted. Wait for someone more experienced than me to provide some more pointers.

bytebone commented 9 months ago

While I assume that the main contributers would already be on top of the situation, let me just quickly sum up some relevant links for this lyrics spec for the curious:

gonic already implements the getLyrics endpoint, which should be able to share unsynced lyrics. But looking at the code, I don't think it does anything.

Just looking at the simple ServeGetSong function provides lots of info how the requests are handled and transformed into responses. You could probably also draw inspiration from the function that serves the cover art regarding file system interaction.

Most importantly, Navidrome seems to already have lyrics support and is also written in go: https://github.com/navidrome/navidrome/blob/master/model/lyrics.go. They don't use any parsing libraries, rather opting for simple regex (which imho is completely sufficient). This may be rather straightforward to apply to gonic.

sentriz commented 9 months ago

would we also support lyrics in audio metadata? and what would the priority be over .lrc files? also, is there any software such as beets or picard that can find and embed/store lyrics?

bytebone commented 9 months ago

If its possible to implement reading from the tag with audiotags, I see no harm in supporting both sources. The OSS spec supports multiple lyrics per individual song, so no problem there.

Edit: TagLib appears to support both SynchronizedLyricsFrame and UnsynchronizedLyricsFrame. I assume that this therefor also applies to audiotags.

Prioritization seems more like a client issue to me; if a client supports the getLyricsBySongId endpoint it should by default handle multiple lyric lists. Where the question is more relevant is the Subsonic getLyrics endpoint, which only supports one unsynced lyrics string. In that case, priority should (imo) be granted to a .lrc file, since that would be placed there with more intent than lyrics from a tag.

For lyric clients, I found this from a quick search: https://lrclib.net/. Note the API and the available client. Or if you want something in go, maybe this is to your liking: https://github.com/fashni/MxLRC-Go.

On another note, does the server need to broadcast the fact that a song has lyrics? I checked my gonic HTTP logs when playing music with Synfonium, and it does not by default query any lyrics endpoints. I see that navidrome has lyrics as part of their song object, but cannot figure out if they broadcast it to clients automatically. And the OSS spec doesn't specify the contents of songs at all.

duckfromdiscord commented 9 months ago

So I take it we will have to fix the existing stubbed getLyrics and also add the getLyrics2 from the RFC?

bytebone commented 9 months ago

So I take it we will have to fix the existing stubbed getLyrics and also add the getLyrics2 from the RFC?

/getLyrics2 is not an endpoint that was implemented. The discussion you linked resulted in the getLyricsBySongId endpoint, which is exclusive to OSS and able to provide multiple (un)synced lyrics per track. That's what would need to be implemented, in addition to "fixing" the /getLyrics stub to actually function and offer one of the available lyrics (for compat with the subsonic spec)

dweymouth commented 8 months ago

FYI lyrics support is being built in Supersonic now and will be in the next release - so it would be a good time for someone to pick up this ticket and do a PR :)

TorchedSammy commented 7 months ago

I've decided to work on both lyric endpoints, currently only fetching from the .lrc files. Does anyone know of any clients that support the new endpoint for synced lyrics? Tempo on android has it on a WIP branch I presume, otherwise it's a debug build.

FYI lyrics support is being built in Supersonic now and will be in the next release - so it would be a good time for someone to pick up this ticket and do a PR :)

I tried it out, make sure to also support the synced lyrics.

Tolriq commented 7 months ago

Symfonium fully support it.