Cache preview frames for Discord video attachments

This commit is contained in:
Fisto
2026-09-16 23:40:46 +02:00
parent 3da0da0ca7
commit caf9b7db3a
6 changed files with 34 additions and 13 deletions
+10 -6
View File
@@ -193,18 +193,17 @@ const DISCORD_HOSTS = new Set(["cdn.discordapp.com", "media.discordapp.net"]);
/**
* The preview target for a media row.
*
* Attachments and stickers: their Discord-hosted URL, resized to a small WebP.
* Attachments and stickers: their Discord-hosted URL, resized to a small WebP. Discord's proxy
* also renders a frame for video files, so attachment videos get a poster for free.
* Embeds: the stored thumbnail or image URL, used as-is (Discord-hosted ones are still resized).
* Returns null when the row has no preview source.
* A bare embed URL is a page, never a preview. Returns null when the row has no preview source.
*/
export function previewUrlFor(media: {
url: string;
kind: string;
previewUrl?: string | null;
}): string | null {
const candidate =
media.previewUrl ??
(media.kind === "image" || media.kind === "gif" ? media.url : null);
const candidate = media.previewUrl ?? media.url;
if (!candidate) return null;
try {
@@ -214,8 +213,13 @@ export function previewUrlFor(media: {
url.searchParams.set("width", "320");
url.searchParams.set("height", "320");
url.searchParams.set("format", "webp");
return url.toString();
}
return url.toString();
if (media.previewUrl || media.kind === "image" || media.kind === "gif") {
return url.toString();
}
return null;
} catch {
return null;
}
+2 -1
View File
@@ -342,7 +342,8 @@ export class ScrapeStore {
* embed thumbnails only when `includeEmbeds` is set (download mode).
*/
pendingPreviews(limit = 5000, includeEmbeds = false): MediaRow[] {
const local = "(kind IN ('image', 'gif') AND (source IS NULL OR source != 'embed'))";
const local =
"((source IS NULL OR source != 'embed') AND kind IN ('image', 'gif', 'video'))";
const condition = includeEmbeds
? `(${local} OR (source = 'embed' AND preview_url IS NOT NULL))`
: local;