동영상의 썸네일이 가끔 흰색으로 잘못 생성되던 버그 수정

This commit is contained in:
static
2025-07-12 05:39:39 +09:00
parent 0d35f0b607
commit 4679b1d6bd
2 changed files with 38 additions and 43 deletions

View File

@@ -54,9 +54,7 @@ export const deleteFileCache = async (fileId: number) => {
export const getFileThumbnailCache = async (fileId: number) => { export const getFileThumbnailCache = async (fileId: number) => {
const thumbnail = loadedThumbnails.get(fileId); const thumbnail = loadedThumbnails.get(fileId);
if (thumbnail) { if (thumbnail) return thumbnail;
return thumbnail;
}
const thumbnailBuffer = await readFile(`/thumbnail/file/${fileId}`); const thumbnailBuffer = await readFile(`/thumbnail/file/${fileId}`);
if (!thumbnailBuffer) return null; if (!thumbnailBuffer) return null;

View File

@@ -12,50 +12,25 @@ const scaleSize = (width: number, height: number, targetSize: number) => {
}; };
}; };
const generateImageThumbnail = (imageUrl: string) => { const capture = (
return new Promise<Blob>((resolve, reject) => { width: number,
const image = new Image(); height: number,
image.onload = () => { drawer: (context: CanvasRenderingContext2D, width: number, height: number) => void,
const canvas = document.createElement("canvas"); targetSize = 250,
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 captureVideoThumbnail = (video: HTMLVideoElement) => {
return new Promise<Blob>((resolve, reject) => { return new Promise<Blob>((resolve, reject) => {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
const { width, height } = scaleSize(video.videoWidth, video.videoHeight, 250); const { width: scaledWidth, height: scaledHeight } = scaleSize(width, height, targetSize);
canvas.width = width; canvas.width = scaledWidth;
canvas.height = height; canvas.height = scaledHeight;
const context = canvas.getContext("2d"); const context = canvas.getContext("2d");
if (!context) { if (!context) {
return reject(new Error("Failed to generate thumbnail")); return reject(new Error("Failed to generate thumbnail"));
} }
context.drawImage(video, 0, 0, width, height); drawer(context, scaledWidth, scaledHeight);
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
if (blob) { if (blob) {
resolve(blob); resolve(blob);
@@ -66,14 +41,36 @@ export const captureVideoThumbnail = (video: HTMLVideoElement) => {
}); });
}; };
const generateImageThumbnail = (imageUrl: string) => {
return new Promise<Blob>((resolve, reject) => {
const image = new Image();
image.onload = () => {
capture(image.width, image.height, (context, width, height) => {
context.drawImage(image, 0, 0, width, height);
})
.then(resolve)
.catch(reject);
};
image.onerror = reject;
image.src = imageUrl;
});
};
export const captureVideoThumbnail = (video: HTMLVideoElement) => {
return capture(video.videoWidth, video.videoHeight, (context, width, height) => {
context.drawImage(video, 0, 0, width, height);
});
};
const generateVideoThumbnail = (videoUrl: string, time = 0) => { const generateVideoThumbnail = (videoUrl: string, time = 0) => {
return new Promise<Blob>((resolve, reject) => { return new Promise<Blob>((resolve, reject) => {
const video = document.createElement("video"); const video = document.createElement("video");
video.onloadeddata = () => { video.onloadedmetadata = () => {
video.currentTime = time; video.currentTime = Math.min(time, video.duration);
}; video.requestVideoFrameCallback(() => {
video.onseeked = () => { captureVideoThumbnail(video).then(resolve).catch(reject);
captureVideoThumbnail(video).then(resolve).catch(reject); });
}; };
video.onerror = reject; video.onerror = reject;