diff --git a/src/lib/modules/thumbnail.ts b/src/lib/modules/thumbnail.ts new file mode 100644 index 0000000..30e931e --- /dev/null +++ b/src/lib/modules/thumbnail.ts @@ -0,0 +1,76 @@ +const scaleSize = (width: number, height: number, targetSize: number) => { + if (width <= targetSize || height <= targetSize) { + return { width, height }; + } + + const scale = targetSize / Math.min(width, height); + return { + width: Math.round(width * scale), + height: Math.round(height * scale), + }; +}; + +export const generateImageThumbnail = (imageUrl: string) => { + return new Promise((resolve, reject) => { + const image = new Image(); + image.onload = () => { + const canvas = document.createElement("canvas"); + const { width, height } = scaleSize(image.width, image.height, 250); + + canvas.width = width; + canvas.height = height; + + const context = canvas.getContext("2d"); + if (!context) { + return reject(new Error("Failed to generate thumbnail")); + } + + context.drawImage(image, 0, 0, width, height); + canvas.toBlob((blob) => { + if (blob) { + resolve(blob); + } else { + reject(new Error("Failed to generate thumbnail")); + } + }, "image/webp"); + }; + image.onerror = reject; + + image.src = imageUrl; + }); +}; + +export const generateVideoThumbnail = (videoUrl: string, time = 0) => { + return new Promise((resolve, reject) => { + const video = document.createElement("video"); + video.onloadeddata = () => { + video.currentTime = time; + }; + video.onseeked = () => { + const canvas = document.createElement("canvas"); + const { width, height } = scaleSize(video.videoWidth, video.videoHeight, 250); + + canvas.width = width; + canvas.height = height; + + const context = canvas.getContext("2d"); + if (!context) { + return reject(new Error("Failed to generate thumbnail")); + } + + context.drawImage(video, 0, 0, width, height); + canvas.toBlob((blob) => { + if (blob) { + resolve(blob); + } else { + reject(new Error("Failed to generate thumbnail")); + } + }, "image/webp"); + }; + video.onerror = reject; + + video.muted = true; + video.playsInline = true; + video.src = videoUrl; + }); +};