perf(web-player): serve YouTube artwork through a caching proxy
The browser used to pull every cover straight from Google, so a search grid plus infinite scroll fired dozens of cross-origin image requests and started coming back as 429. Covers now go through /api/youtube/thumbnail, which resizes the upstream URL, caches the bytes in memory, collapses duplicate in-flight fetches, caps the concurrency against Google and backs off when it answers 429. Responses are immutable for a month and revalidate with an ETag, and serving them same-origin also lets the accent extractor read the pixels.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { browser } from '$app/environment';
|
||||
import { HUES, accentForHue, gradientForHue, hueFor } from '$lib/theme/color';
|
||||
import { extractAccent, type Accent } from '$lib/theme/palette';
|
||||
import { thumbnailSrc } from '$lib/thumbnails';
|
||||
|
||||
export type TrackSourceKind = 'local' | 'youtube';
|
||||
|
||||
@@ -190,7 +191,8 @@ class PlayerState {
|
||||
navigator.mediaSession.metadata = null;
|
||||
return;
|
||||
}
|
||||
const artwork = track.coverUrl ?? `/api/tracks/${track.id}/cover?size=small`;
|
||||
const artwork =
|
||||
thumbnailSrc(track.coverUrl, 'medium') ?? `/api/tracks/${track.id}/cover?size=small`;
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: track.title,
|
||||
artist: track.artist,
|
||||
@@ -242,7 +244,9 @@ class PlayerState {
|
||||
this.gradientColor = cached.gradient;
|
||||
return;
|
||||
}
|
||||
const result = await extractAccent(coverUrl ?? `/api/tracks/${id}/cover?size=small`);
|
||||
const result = await extractAccent(
|
||||
thumbnailSrc(coverUrl, 'small') ?? `/api/tracks/${id}/cover?size=small`
|
||||
);
|
||||
if (this.currentId !== id) return;
|
||||
if (result) {
|
||||
this.#accentCache.set(key, result);
|
||||
|
||||
Reference in New Issue
Block a user