feat: enhance thumbnail generation in media scanning process
- Added error handling for thumbnail generation, providing fallback thumbnails for videos and photos if generation fails. - Updated database insertion logic to reflect the final thumbnail URL used, improving media management reliability.
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
||||
<rect width="320" height="240" fill="#1f2937"/>
|
||||
<rect x="90" y="80" width="140" height="80" rx="4" stroke="#6b7280" stroke-width="2" fill="none"/>
|
||||
<circle cx="160" cy="120" r="25" stroke="#6b7280" stroke-width="2" fill="none"/>
|
||||
<circle cx="160" cy="120" r="12" stroke="#6b7280" stroke-width="1" fill="none"/>
|
||||
<text x="160" y="180" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#9ca3af">Photo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 543 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
||||
<rect width="320" height="240" fill="#1f2937"/>
|
||||
<circle cx="160" cy="120" r="40" stroke="#6b7280" stroke-width="2" fill="none"/>
|
||||
<polygon points="140,100 180,120 140,140" fill="#6b7280"/>
|
||||
<text x="160" y="180" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#9ca3af">Video</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 420 B |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
|
@ -70,10 +70,21 @@ const scanLibrary = async (library: { id: number; path: string }) => {
|
|||
fs.mkdirSync(thumbnailsDir, { recursive: true });
|
||||
}
|
||||
|
||||
let finalThumbnailUrl = thumbnailUrl;
|
||||
let thumbnailGenerated = false;
|
||||
|
||||
try {
|
||||
if (isVideo) {
|
||||
await generateVideoThumbnail(file, thumbnailPath);
|
||||
thumbnailGenerated = true;
|
||||
} else if (isPhoto) {
|
||||
await generatePhotoThumbnail(file, thumbnailPath);
|
||||
thumbnailGenerated = true;
|
||||
}
|
||||
} catch (thumbnailError) {
|
||||
console.warn(`Thumbnail generation failed for ${file}:`, thumbnailError);
|
||||
// Use fallback thumbnail based on media type
|
||||
finalThumbnailUrl = isVideo ? "/placeholder-video.svg" : "/placeholder-photo.svg";
|
||||
}
|
||||
|
||||
const media = {
|
||||
|
|
@ -82,12 +93,14 @@ const scanLibrary = async (library: { id: number; path: string }) => {
|
|||
type: mediaType,
|
||||
title: title,
|
||||
size: stats.size,
|
||||
thumbnail: thumbnailUrl,
|
||||
thumbnail: finalThumbnailUrl,
|
||||
};
|
||||
|
||||
db.prepare(
|
||||
"INSERT INTO media (library_id, path, type, title, size, thumbnail) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
).run(media.library_id, media.path, media.type, media.title, media.size, media.thumbnail);
|
||||
|
||||
console.log(`Successfully inserted ${mediaType}: ${title}${thumbnailGenerated ? ' with thumbnail' : ' with fallback thumbnail'}`);
|
||||
} catch (error: any) {
|
||||
if (error.code !== "SQLITE_CONSTRAINT_UNIQUE") {
|
||||
console.error(`Error inserting media: ${file}`, error);
|
||||
|
|
|
|||