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:
2026-07-20 17:36:41 +02:00
parent dd3150e3d4
commit 2691c40da8
6 changed files with 262 additions and 3 deletions
@@ -1,6 +1,7 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import { gradientForHue } from '$lib/theme/color';
import { thumbnailSrc } from '$lib/thumbnails';
interface Props {
trackId: string | number;
@@ -25,7 +26,9 @@
let failed = $state(false);
let loaded = $state(false);
const imageSrc = $derived(src ?? `/api/tracks/${trackId}/cover?size=${size}`);
const imageSrc = $derived(
src ? (thumbnailSrc(src, size) ?? src) : `/api/tracks/${trackId}/cover?size=${size}`
);
$effect(() => {
imageSrc;
@@ -43,6 +46,8 @@
src={imageSrc}
{alt}
loading="lazy"
decoding="async"
fetchpriority="low"
onload={() => (loaded = true)}
onerror={() => (failed = true)}
class="h-full w-full object-cover"