From 85298b861d974c7a9cca80c94de0568aeb5e7299 Mon Sep 17 00:00:00 2001 From: codey Date: Tue, 25 Nov 2025 13:06:07 -0500 Subject: [PATCH] minor --- endpoints/lyric_search.py | 4 +- endpoints/radio.py | 76 ++++++++++++++++++++-------------- lyric_search/sources/lrclib.py | 7 +++- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/endpoints/lyric_search.py b/endpoints/lyric_search.py index feba254..38cfa91 100644 --- a/endpoints/lyric_search.py +++ b/endpoints/lyric_search.py @@ -80,9 +80,9 @@ class LyricSearch(FastAPI): ) for endpoint, handler in self.endpoints.items(): - times: int = 20 + times: int = 5 seconds: int = 2 - rate_limit: tuple[int, int] = (2, 3) # Default; (Times, Seconds) + rate_limit: tuple[int, int] = (times, seconds) # Default; (Times, Seconds) _schema_include = endpoint in ["lyric/search"] if ( diff --git a/endpoints/radio.py b/endpoints/radio.py index de2e4f9..be1d743 100644 --- a/endpoints/radio.py +++ b/endpoints/radio.py @@ -307,7 +307,7 @@ class Radio(FastAPI): } ) - async def album_art_handler( + def album_art_handler( self, request: Request, track_id: Optional[int] = None, station: Station = "main" ) -> Response: @@ -371,6 +371,14 @@ class Radio(FastAPI): ret_obj.pop("file_path") return JSONResponse(content=ret_obj) + def _bg_cache_art(self, track_id: int, file_path: str): + try: + album_art = self.radio_util.get_album_art(track_id=track_id) + if not album_art: + self.radio_util.cache_album_art(track_id, file_path) + except Exception as e: + logging.error(f"Background art cache error: {e}") + async def radio_get_next( self, data: ValidRadioNextRequest, @@ -448,13 +456,7 @@ class Radio(FastAPI): logging.info("radio_get_next Exception: %s", str(e)) traceback.print_exc() - try: - album_art = self.radio_util.get_album_art(track_id=next["id"]) - if not album_art: - self.radio_util.cache_album_art(next["id"], next["file_path"]) - except Exception as e: - logging.info("radio_get_next Exception: %s", str(e)) - traceback.print_exc() + background_tasks.add_task(self._bg_cache_art, next["id"], next["file_path"]) return JSONResponse(content=next) @@ -496,8 +498,12 @@ class Radio(FastAPI): }, ) - search: bool = self.radio_util.search_db( - artistsong=artistsong, artist=artist, song=song, station=data.station + loop = asyncio.get_running_loop() + search: bool = await loop.run_in_executor( + None, + lambda: self.radio_util.search_db( + artistsong=artistsong, artist=artist, song=song, station=data.station + ) ) if data.alsoSkip: await self.radio_util._ls_skip(data.station) @@ -764,7 +770,22 @@ class Radio(FastAPI): logging.info(f"[LRC] Starting fetch for {station}: {artist} - {title}") - # Try SR first with timeout + # Try LRCLib first with timeout + try: + async with asyncio.timeout(10.0): # 10 second timeout + logging.info("[LRC] Trying LRCLib") + lrclib_result = await self.lrclib.search(artist, title, plain=False, raw=True) + if lrclib_result and lrclib_result.lyrics and isinstance(lrclib_result.lyrics, str): + logging.info("[LRC] Found from LRCLib") + return lrclib_result.lyrics, "LRCLib" + except asyncio.TimeoutError: + logging.warning("[LRC] LRCLib fetch timed out") + except Exception as e: + logging.error(f"[LRC] LRCLib fetch error: {e}") + + logging.info("[LRC] LRCLib fetch completed without results") + + # Try SR as fallback with timeout try: async with asyncio.timeout(10.0): # 10 second timeout lrc = await self.sr_util.get_lrc_by_artist_song( @@ -778,21 +799,6 @@ class Radio(FastAPI): except Exception as e: logging.error(f"[LRC] SR fetch error: {e}") - logging.info("[LRC] SR fetch completed without results") - - # Try LRCLib as fallback with timeout - try: - async with asyncio.timeout(10.0): # 10 second timeout - logging.info("[LRC] Trying LRCLib fallback") - lrclib_result = await self.lrclib.search(artist, title, plain=False) - if lrclib_result and lrclib_result.lyrics and isinstance(lrclib_result.lyrics, str): - logging.info("[LRC] Found from LRCLib") - return lrclib_result.lyrics, "LRCLib" - except asyncio.TimeoutError: - logging.warning("[LRC] LRCLib fetch timed out") - except Exception as e: - logging.error(f"[LRC] LRCLib fetch error: {e}") - logging.info("[LRC] No lyrics found from any source") return None, "None" except Exception as e: @@ -804,11 +810,21 @@ class Radio(FastAPI): try: async with self.lrc_cache_locks[station]: self.lrc_cache.pop(station, None) - lrc, source = await self._fetch_and_cache_lrc(station, track_json) - if lrc: - self.lrc_cache[station] = lrc + + lrc, source = await self._fetch_and_cache_lrc(station, track_json) + + async with self.lrc_cache_locks[station]: + # Verify we are still on the same song + current_track = self.radio_util.now_playing.get(station) + if current_track and current_track.get("uuid") == track_json.get("uuid"): + if lrc: + self.lrc_cache[station] = lrc + else: + self.lrc_cache[station] = None else: - self.lrc_cache[station] = None + logging.info(f"[LRC] Discarding fetch result for {station} as track changed.") + return + if lrc: await self.broadcast_lrc(station, lrc, source) except Exception as e: diff --git a/lyric_search/sources/lrclib.py b/lyric_search/sources/lrclib.py index 005ad2c..7907629 100644 --- a/lyric_search/sources/lrclib.py +++ b/lyric_search/sources/lrclib.py @@ -26,6 +26,7 @@ class LRCLib: song: str, plain: Optional[bool] = True, duration: Optional[int] = None, + raw: bool = False, ) -> Optional[LyricsResult]: """ LRCLib Local Database Search @@ -34,6 +35,7 @@ class LRCLib: song (str): the song to search plain (bool): return plain lyrics (True) or synced lyrics (False) duration (int): optional track duration for better matching + raw (bool): return raw LRC string instead of parsed object (only for synced) Returns: Optional[LyricsResult]: The result, if found - None otherwise. """ @@ -119,7 +121,10 @@ class LRCLib: logging.info("No synced lyrics available on %s", self.label) return None returned_lyrics = best_match.synced_lyrics - lrc_obj = self.datautils.create_lrc_object(returned_lyrics) + if raw: + lrc_obj = returned_lyrics + else: + lrc_obj = self.datautils.create_lrc_object(returned_lyrics) # Calculate match confidence input_track = f"{artist} - {song}"