Implement songLyrics extension: getLyricsBySongId with real word/syllable cues

Adds getLyricsBySongId (versions 1 and 2 of the songLyrics extension,
gated by the enhanced param): returns every stored structuredLyrics
entry for a song, including line-level start times for synced lyrics
and, only when a source actually provided word/syllable timing (an
Enhanced LRC sidecar) and enhanced=true was requested, cueLine/cue
data with the precomputed UTF-8 byte offsets. Plain and non-enhanced
synced lyrics never get fabricated cue data.

Removes the now-dead SetSongLyrics writer (superseded by
database.InsertLyrics); SongLyricsPlainText keeps serving the legacy
getLyrics endpoint unchanged.

Adds a scanner integration test proving a sidecar .lrc (with an
Enhanced LRC line) is discovered and indexed during a real scan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014r98AtcBbevpscWLsfwVvv
This commit is contained in:
2026-08-23 08:19:41 -05:00
co-authored by Claude Sonnet 5
parent e48f063f03
commit ec28053d36
5 changed files with 363 additions and 53 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ func TestGetOpenSubsonicExtensions(t *testing.T) {
// set once Phase 3 is done.
for _, want := range []string{
"apiKeyAuthentication", "formPost", "getPodcastEpisode", "topSongsByArtistId", "transcodeOffset",
"indexBasedQueue", "playbackReport",
"indexBasedQueue", "playbackReport", "songLyrics",
} {
if !names[want] {
t.Errorf("extension %q not advertised: %v", want, names)