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:
@@ -51,3 +51,30 @@ export const apiConfig = {
|
||||
return (env.API_BASE_URL ?? '').replace(/\/+$/, '');
|
||||
}
|
||||
};
|
||||
|
||||
export const thumbnailConfig = {
|
||||
get maxAgeSeconds() {
|
||||
return positiveInt(env.THUMBNAIL_CACHE_MAX_AGE_SECONDS, 30 * DAY_SECONDS);
|
||||
},
|
||||
get failureCacheSeconds() {
|
||||
return positiveInt(env.THUMBNAIL_FAILURE_CACHE_SECONDS, 300);
|
||||
},
|
||||
get memoryCacheBytes() {
|
||||
return positiveInt(env.THUMBNAIL_CACHE_BYTES, 128 * 1024 * 1024);
|
||||
},
|
||||
get maxConcurrentFetches() {
|
||||
return positiveInt(env.THUMBNAIL_MAX_CONCURRENT_FETCHES, 4);
|
||||
},
|
||||
get fetchTimeoutMs() {
|
||||
return positiveInt(env.THUMBNAIL_FETCH_TIMEOUT_MS, 8000);
|
||||
},
|
||||
get cooldownSeconds() {
|
||||
return positiveInt(env.THUMBNAIL_COOLDOWN_SECONDS, 30);
|
||||
},
|
||||
get maxCooldownSeconds() {
|
||||
return positiveInt(env.THUMBNAIL_MAX_COOLDOWN_SECONDS, 300);
|
||||
},
|
||||
get maxSize() {
|
||||
return positiveInt(env.THUMBNAIL_MAX_SIZE, 720);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user