From 1a01871cfc7a6405ed1140c7ed415e170843e40d Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Tue, 1 Jul 2025 01:13:14 +0200 Subject: refactor: update media processing to use width and height instead of aspect ratio --- apps/web/src/lib/media-processing.ts | 166 ++++++++++++++-------------- apps/web/src/lib/storage/storage-service.ts | 6 +- apps/web/src/lib/storage/types.ts | 5 +- 3 files changed, 92 insertions(+), 85 deletions(-) (limited to 'apps/web/src/lib') diff --git a/apps/web/src/lib/media-processing.ts b/apps/web/src/lib/media-processing.ts index daf22b34..4c1294ae 100644 --- a/apps/web/src/lib/media-processing.ts +++ b/apps/web/src/lib/media-processing.ts @@ -1,81 +1,85 @@ -import { toast } from "sonner"; -import { - getFileType, - generateVideoThumbnail, - getMediaDuration, - getImageAspectRatio, - type MediaItem, -} from "@/stores/media-store"; -// import { generateThumbnail, getVideoInfo } from "./ffmpeg-utils"; // Temporarily disabled - -export interface ProcessedMediaItem extends Omit {} - -export async function processMediaFiles( - files: FileList | File[], - onProgress?: (progress: number) => void -): Promise { - const fileArray = Array.from(files); - const processedItems: ProcessedMediaItem[] = []; - - const total = fileArray.length; - let completed = 0; - - for (const file of fileArray) { - const fileType = getFileType(file); - - if (!fileType) { - toast.error(`Unsupported file type: ${file.name}`); - continue; - } - - const url = URL.createObjectURL(file); - let thumbnailUrl: string | undefined; - let duration: number | undefined; - let aspectRatio: number = 16 / 9; // Default fallback - - try { - if (fileType === "image") { - // Get image aspect ratio - aspectRatio = await getImageAspectRatio(file); - } else if (fileType === "video") { - // Use basic thumbnail generation for now - const videoResult = await generateVideoThumbnail(file); - thumbnailUrl = videoResult.thumbnailUrl; - aspectRatio = videoResult.aspectRatio; - } else if (fileType === "audio") { - // For audio, use a square aspect ratio - aspectRatio = 1; - } - - // Get duration for videos and audio (if not already set by FFmpeg) - if ((fileType === "video" || fileType === "audio") && !duration) { - duration = await getMediaDuration(file); - } - - processedItems.push({ - name: file.name, - type: fileType, - file, - url, - thumbnailUrl, - duration, - aspectRatio, - }); - - // Yield back to the event loop to keep the UI responsive - await new Promise((resolve) => setTimeout(resolve, 0)); - - completed += 1; - if (onProgress) { - const percent = Math.round((completed / total) * 100); - onProgress(percent); - } - } catch (error) { - console.error("Error processing file:", file.name, error); - toast.error(`Failed to process ${file.name}`); - URL.revokeObjectURL(url); // Clean up on error - } - } - - return processedItems; -} +import { toast } from "sonner"; +import { + getFileType, + generateVideoThumbnail, + getMediaDuration, + getImageDimensions, + type MediaItem, +} from "@/stores/media-store"; +// import { generateThumbnail, getVideoInfo } from "./ffmpeg-utils"; // Temporarily disabled + +export interface ProcessedMediaItem extends Omit {} + +export async function processMediaFiles( + files: FileList | File[], + onProgress?: (progress: number) => void +): Promise { + const fileArray = Array.from(files); + const processedItems: ProcessedMediaItem[] = []; + + const total = fileArray.length; + let completed = 0; + + for (const file of fileArray) { + const fileType = getFileType(file); + + if (!fileType) { + toast.error(`Unsupported file type: ${file.name}`); + continue; + } + + const url = URL.createObjectURL(file); + let thumbnailUrl: string | undefined; + let duration: number | undefined; + let width: number | undefined; + let height: number | undefined; + + try { + if (fileType === "image") { + // Get image dimensions + const dimensions = await getImageDimensions(file); + width = dimensions.width; + height = dimensions.height; + } else if (fileType === "video") { + // Use basic thumbnail generation for now + const videoResult = await generateVideoThumbnail(file); + thumbnailUrl = videoResult.thumbnailUrl; + width = videoResult.width; + height = videoResult.height; + } else if (fileType === "audio") { + // For audio, we don't set width/height (they'll be undefined) + } + + // Get duration for videos and audio (if not already set by FFmpeg) + if ((fileType === "video" || fileType === "audio") && !duration) { + duration = await getMediaDuration(file); + } + + processedItems.push({ + name: file.name, + type: fileType, + file, + url, + thumbnailUrl, + duration, + width, + height, + }); + + // Yield back to the event loop to keep the UI responsive + await new Promise((resolve) => setTimeout(resolve, 0)); + + completed += 1; + if (onProgress) { + const percent = Math.round((completed / total) * 100); + onProgress(percent); + } + } catch (error) { + console.error("Error processing file:", file.name, error); + toast.error(`Failed to process ${file.name}`); + URL.revokeObjectURL(url); // Clean up on error + } + } + + return processedItems; +} diff --git a/apps/web/src/lib/storage/storage-service.ts b/apps/web/src/lib/storage/storage-service.ts index 5582ae29..65b3c134 100644 --- a/apps/web/src/lib/storage/storage-service.ts +++ b/apps/web/src/lib/storage/storage-service.ts @@ -94,7 +94,8 @@ class StorageService { type: mediaItem.type, size: mediaItem.file.size, lastModified: mediaItem.file.lastModified, - aspectRatio: mediaItem.aspectRatio, + width: mediaItem.width, + height: mediaItem.height, duration: mediaItem.duration, }; @@ -118,7 +119,8 @@ class StorageService { type: metadata.type, file, url, - aspectRatio: metadata.aspectRatio, + width: metadata.width, + height: metadata.height, duration: metadata.duration, // thumbnailUrl would need to be regenerated or cached separately }; diff --git a/apps/web/src/lib/storage/types.ts b/apps/web/src/lib/storage/types.ts index d56deebd..7ad18e19 100644 --- a/apps/web/src/lib/storage/types.ts +++ b/apps/web/src/lib/storage/types.ts @@ -14,7 +14,8 @@ export interface MediaFileData { type: "image" | "video" | "audio"; size: number; lastModified: number; - aspectRatio: number; + width?: number; + height?: number; duration?: number; // File will be stored separately in OPFS } @@ -38,4 +39,4 @@ declare global { values(): AsyncIterableIterator; entries(): AsyncIterableIterator<[string, FileSystemHandle]>; } -} \ No newline at end of file +} -- cgit v1.3.1