Fix lyrics fetching and disable prefetching

- Fix LyricsPrefetchService to use server API key for Jellyfin lyrics checks
- Remove Spotify lyrics caching (local Docker container is fast)
- Disable lyrics prefetching service (not needed - Jellyfin/Spotify are fast)
- Add POST /api/admin/cache/clear-lyrics endpoint to clear LRCLIB cache
- Only LRCLIB lyrics are cached now (external API)
This commit is contained in:
2026-02-06 23:48:18 -05:00
parent 64e2004bdc
commit b99a199ef3
4 changed files with 33 additions and 18 deletions

View File

@@ -1738,6 +1738,30 @@ public class AdminController : ControllerBase
}); });
} }
/// <summary>
/// Clear all cached lyrics (LRCLIB only - Jellyfin and Spotify lyrics are not cached)
/// </summary>
[HttpPost("cache/clear-lyrics")]
public async Task<IActionResult> ClearLyricsCache()
{
_logger.LogInformation("Lyrics cache clear requested from admin UI");
var clearedRedisKeys = 0;
// Clear all lyrics cache keys (pattern-based deletion)
// This includes LRCLIB lyrics and manual mappings
var lyricsKeysDeleted = await _cache.DeleteByPatternAsync("lyrics:*");
clearedRedisKeys += lyricsKeysDeleted;
_logger.LogInformation("Lyrics cache cleared: {RedisKeys} Redis keys deleted", clearedRedisKeys);
return Ok(new {
message = "Lyrics cache cleared successfully",
redisKeysDeleted = clearedRedisKeys,
note = "Only LRCLIB lyrics are cached. Jellyfin and Spotify lyrics are fetched on-demand (fast)."
});
}
/// <summary> /// <summary>
/// Restart the allstarr container to apply configuration changes /// Restart the allstarr container to apply configuration changes
/// </summary> /// </summary>

View File

@@ -568,8 +568,9 @@ builder.Services.AddSingleton<allstarr.Services.Spotify.SpotifyTrackMatchingServ
builder.Services.AddHostedService(sp => sp.GetRequiredService<allstarr.Services.Spotify.SpotifyTrackMatchingService>()); builder.Services.AddHostedService(sp => sp.GetRequiredService<allstarr.Services.Spotify.SpotifyTrackMatchingService>());
// Register lyrics prefetch service (prefetches lyrics for all playlist tracks) // Register lyrics prefetch service (prefetches lyrics for all playlist tracks)
builder.Services.AddSingleton<allstarr.Services.Lyrics.LyricsPrefetchService>(); // DISABLED - No need to prefetch since Jellyfin and Spotify lyrics are fast
builder.Services.AddHostedService(sp => sp.GetRequiredService<allstarr.Services.Lyrics.LyricsPrefetchService>()); // builder.Services.AddSingleton<allstarr.Services.Lyrics.LyricsPrefetchService>();
// builder.Services.AddHostedService(sp => sp.GetRequiredService<allstarr.Services.Lyrics.LyricsPrefetchService>());
// Register MusicBrainz service for metadata enrichment // Register MusicBrainz service for metadata enrichment
builder.Services.Configure<allstarr.Models.Settings.MusicBrainzSettings>(options => builder.Services.Configure<allstarr.Models.Settings.MusicBrainzSettings>(options =>

View File

@@ -406,9 +406,9 @@ public class LyricsPrefetchService : BackgroundService
} }
// Directly check if this track has lyrics using the item ID // Directly check if this track has lyrics using the item ID
var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsync( // Use internal method with server API key since this is a background operation
var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsyncInternal(
$"Audio/{jellyfinItemId}/Lyrics", $"Audio/{jellyfinItemId}/Lyrics",
null,
null); null);
if (lyricsResult != null && lyricsStatusCode == 200) if (lyricsResult != null && lyricsStatusCode == 200)
@@ -455,7 +455,7 @@ public class LyricsPrefetchService : BackgroundService
["limit"] = "5" // Get a few results to find best match ["limit"] = "5" // Get a few results to find best match
}; };
var (searchResult, statusCode) = await proxyService.GetJsonAsync("Items", searchParams, null); var (searchResult, statusCode) = await proxyService.GetJsonAsyncInternal("Items", searchParams);
if (searchResult == null || statusCode != 200) if (searchResult == null || statusCode != 200)
{ {
@@ -511,9 +511,9 @@ public class LyricsPrefetchService : BackgroundService
} }
// Check if this track has lyrics // Check if this track has lyrics
var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsync( // Use internal method with server API key since this is a background operation
var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsyncInternal(
$"Audio/{bestMatchId}/Lyrics", $"Audio/{bestMatchId}/Lyrics",
null,
null); null);
if (lyricsResult != null && lyricsStatusCode == 200) if (lyricsResult != null && lyricsStatusCode == 200)

View File

@@ -63,15 +63,7 @@ public class SpotifyLyricsService
// Normalize track ID (remove URI prefix if present) // Normalize track ID (remove URI prefix if present)
spotifyTrackId = ExtractTrackId(spotifyTrackId); spotifyTrackId = ExtractTrackId(spotifyTrackId);
// Check cache // NO CACHING - Spotify lyrics come from local Docker container (fast)
var cacheKey = $"spotify:lyrics:{spotifyTrackId}";
var cached = await _cache.GetAsync<SpotifyLyricsResult>(cacheKey);
if (cached != null)
{
_logger.LogDebug("Returning cached Spotify lyrics for track {TrackId}", spotifyTrackId);
return cached;
}
try try
{ {
var url = $"{_settings.LyricsApiUrl}/?trackid={spotifyTrackId}&format=id3"; var url = $"{_settings.LyricsApiUrl}/?trackid={spotifyTrackId}&format=id3";
@@ -92,8 +84,6 @@ public class SpotifyLyricsService
if (result != null) if (result != null)
{ {
// Cache for 30 days (lyrics don't change)
await _cache.SetAsync(cacheKey, result, TimeSpan.FromDays(30));
_logger.LogInformation("Got Spotify lyrics from sidecar for track {TrackId} ({LineCount} lines)", _logger.LogInformation("Got Spotify lyrics from sidecar for track {TrackId} ({LineCount} lines)",
spotifyTrackId, result.Lines.Count); spotifyTrackId, result.Lines.Count);
} }