perf(apple): isolate lyrics from audio preparation
CI / build-and-test (push) Canceled after 0s
CI / release-critical-tests (push) Canceled after 0s
CI / csharp-format (push) Canceled after 0s
CI / webui (push) Canceled after 0s
CI / apple-contracts (push) Canceled after 0s
CI / compose-contracts (push) Canceled after 0s
CI / release-manifest (push) Canceled after 0s

This commit is contained in:
joshpatra committed 2026-09-11 09:22:30 -04:00
1 parent e1e67275d9
commit adf3c585a3
3 files changed
+46 -2

No files matched your search

+19 -1
View File
@@ -366,11 +366,29 @@ def create_app(
async def lyrics_song(song_id: str) -> dict[str, str]:
try:
song_url(config.storefront, song_id)
canonical_url = await catalog_client.song_url(song_id)
if canonical_url is None:
raise HTTPException(status_code=404, detail="song_not_found")
url, _ = safe_apple_url(canonical_url)
except ValueError:
raise HTTPException(status_code=400, detail="invalid_song_id") from None
except httpx.HTTPError:
raise HTTPException(status_code=502, detail="catalog_unavailable") from None
cached = config.data_root / "lyrics" / f"{song_id}.lrc"
if not cached.is_file():
await prepare_song(song_id, "alac-16-44")
root = config.data_root / "artifacts" / uuid.uuid4().hex
try:
lyrics = await process_runner.download_lyrics(
url, root / "output", root / "temporary")
cached.parent.mkdir(exist_ok=True, mode=0o750)
partial = cached.with_suffix(".lrc.partial")
shutil.copyfile(lyrics[0], partial)
partial.replace(cached)
except ProcessFailure as exc:
status = 504 if exc.code == "process_timeout" else 404
raise HTTPException(status_code=status, detail=exc.code) from None
finally:
shutil.rmtree(root, ignore_errors=True)
if not cached.is_file():
raise HTTPException(status_code=404, detail="lyrics_not_found")
try:
+18 -1
View File
@@ -62,6 +62,19 @@ class BoundedProcessRunner:
return retained.decode("utf-8", errors="replace")
async def download(self, url: str, quality: str, output: Path, temporary: Path) -> list[Path]:
return await self._download(url, quality, output, temporary, lyrics_only=False)
async def download_lyrics(self, url: str, output: Path, temporary: Path) -> list[Path]:
return await self._download(url, "aac-he", output, temporary, lyrics_only=True)
async def _download(
self,
url: str,
quality: str,
output: Path,
temporary: Path,
lyrics_only: bool,
) -> list[Path]:
output.mkdir(parents=True, exist_ok=False, mode=0o750)
temporary.mkdir(parents=True, exist_ok=False, mode=0o750)
argv = [
@@ -79,11 +92,15 @@ class BoundedProcessRunner:
]
if self._settings.cookies_path:
argv.extend(["--cookies-path", str(self._settings.cookies_path)])
if lyrics_only:
argv.append("--synced-lyrics-only")
argv.append(url)
result = await self.execute(argv, temporary)
if result.return_code != 0:
raise ProcessFailure("gamdl_failed")
artifacts = safe_files(output, {".m4a", ".flac", ".mp4", ".m4v", ".lrc", ".srt", ".ttml", ".jpg", ".png"})
artifacts = safe_files(output, {".lrc"} if lyrics_only else {
".m4a", ".flac", ".mp4", ".m4v", ".lrc", ".srt", ".ttml", ".jpg", ".png"
})
if not artifacts:
raise ProcessFailure("artifact_missing")
return artifacts
@@ -102,6 +102,14 @@ class FakeRunner:
lyrics.write_text("[00:01.00]Fixture lyrics\n", encoding="utf-8")
return [artifact, lyrics]
async def download_lyrics(self, url: str, output: Path, temporary: Path) -> list[Path]:
self.calls.append((url, "lyrics"))
output.mkdir(parents=True, exist_ok=False)
temporary.mkdir(parents=True, exist_ok=False)
lyrics = output / "fixture.lrc"
lyrics.write_text("[00:01.00]Fixture lyrics\n", encoding="utf-8")
return [lyrics]
async def to_flac(self, source: Path, target: Path) -> Path:
self.transcodes.append("file")
target.write_bytes(b"fLaCfixture")
@@ -330,6 +338,7 @@ def test_song_lyrics_use_gamdl_artifact_and_cache(client):
calls = len(client[2].calls)
assert client[0].get("/api/lyrics/103").status_code == 200
assert len(client[2].calls) == calls
assert client[2].calls == [("https://music.apple.com/us/album/fixture/1?i=103", "lyrics")]
@pytest.mark.asyncio