refactor: update media processing to use width and height instead of aspect ratio
This commit is contained in:
@ -5,7 +5,11 @@ import {
|
||||
type TimelineClip,
|
||||
type TimelineTrack,
|
||||
} from "@/stores/timeline-store";
|
||||
import { useMediaStore, type MediaItem } from "@/stores/media-store";
|
||||
import {
|
||||
useMediaStore,
|
||||
type MediaItem,
|
||||
getMediaAspectRatio,
|
||||
} from "@/stores/media-store";
|
||||
import { usePlaybackStore } from "@/stores/playback-store";
|
||||
import { useEditorStore } from "@/stores/editor-store";
|
||||
import { VideoPlayer } from "@/components/ui/video-player";
|
||||
@ -262,7 +266,7 @@ function PreviewToolbar({ hasAnyClips }: { hasAnyClips: boolean }) {
|
||||
mediaItem &&
|
||||
(mediaItem.type === "video" || mediaItem.type === "image")
|
||||
) {
|
||||
return mediaItem.aspectRatio || 16 / 9; // Default to 16:9 if aspectRatio not available
|
||||
return getMediaAspectRatio(mediaItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
getFileType,
|
||||
generateVideoThumbnail,
|
||||
getMediaDuration,
|
||||
getImageAspectRatio,
|
||||
getImageDimensions,
|
||||
type MediaItem,
|
||||
} from "@/stores/media-store";
|
||||
// import { generateThumbnail, getVideoInfo } from "./ffmpeg-utils"; // Temporarily disabled
|
||||
@ -31,20 +31,23 @@ export async function processMediaFiles(
|
||||
const url = URL.createObjectURL(file);
|
||||
let thumbnailUrl: string | undefined;
|
||||
let duration: number | undefined;
|
||||
let aspectRatio: number = 16 / 9; // Default fallback
|
||||
let width: number | undefined;
|
||||
let height: number | undefined;
|
||||
|
||||
try {
|
||||
if (fileType === "image") {
|
||||
// Get image aspect ratio
|
||||
aspectRatio = await getImageAspectRatio(file);
|
||||
// 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;
|
||||
aspectRatio = videoResult.aspectRatio;
|
||||
width = videoResult.width;
|
||||
height = videoResult.height;
|
||||
} else if (fileType === "audio") {
|
||||
// For audio, use a square aspect ratio
|
||||
aspectRatio = 1;
|
||||
// For audio, we don't set width/height (they'll be undefined)
|
||||
}
|
||||
|
||||
// Get duration for videos and audio (if not already set by FFmpeg)
|
||||
@ -59,7 +62,8 @@ export async function processMediaFiles(
|
||||
url,
|
||||
thumbnailUrl,
|
||||
duration,
|
||||
aspectRatio,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
|
||||
// Yield back to the event loop to keep the UI responsive
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ export interface MediaItem {
|
||||
url: string; // Object URL for preview
|
||||
thumbnailUrl?: string; // For video thumbnails
|
||||
duration?: number; // For video/audio duration
|
||||
aspectRatio: number; // width / height
|
||||
width?: number; // For video/image width
|
||||
height?: number; // For video/image height
|
||||
}
|
||||
|
||||
interface MediaStore {
|
||||
@ -40,14 +41,17 @@ export const getFileType = (file: File): "image" | "video" | "audio" | null => {
|
||||
return null;
|
||||
};
|
||||
|
||||
// Helper function to get image aspect ratio
|
||||
export const getImageAspectRatio = (file: File): Promise<number> => {
|
||||
// Helper function to get image dimensions
|
||||
export const getImageDimensions = (
|
||||
file: File
|
||||
): Promise<{ width: number; height: number }> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
|
||||
img.addEventListener("load", () => {
|
||||
const aspectRatio = img.naturalWidth / img.naturalHeight;
|
||||
resolve(aspectRatio);
|
||||
const width = img.naturalWidth;
|
||||
const height = img.naturalHeight;
|
||||
resolve({ width, height });
|
||||
img.remove();
|
||||
});
|
||||
|
||||
@ -60,10 +64,10 @@ export const getImageAspectRatio = (file: File): Promise<number> => {
|
||||
});
|
||||
};
|
||||
|
||||
// Helper function to generate video thumbnail and get aspect ratio
|
||||
// Helper function to generate video thumbnail and get dimensions
|
||||
export const generateVideoThumbnail = (
|
||||
file: File
|
||||
): Promise<{ thumbnailUrl: string; aspectRatio: number }> => {
|
||||
): Promise<{ thumbnailUrl: string; width: number; height: number }> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const video = document.createElement("video");
|
||||
const canvas = document.createElement("canvas");
|
||||
@ -85,9 +89,10 @@ export const generateVideoThumbnail = (
|
||||
video.addEventListener("seeked", () => {
|
||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||
const thumbnailUrl = canvas.toDataURL("image/jpeg", 0.8);
|
||||
const aspectRatio = video.videoWidth / video.videoHeight;
|
||||
const width = video.videoWidth;
|
||||
const height = video.videoHeight;
|
||||
|
||||
resolve({ thumbnailUrl, aspectRatio });
|
||||
resolve({ thumbnailUrl, width, height });
|
||||
|
||||
// Cleanup
|
||||
video.remove();
|
||||
@ -127,6 +132,14 @@ export const getMediaDuration = (file: File): Promise<number> => {
|
||||
});
|
||||
};
|
||||
|
||||
// Helper to get aspect ratio from MediaItem
|
||||
export const getMediaAspectRatio = (item: MediaItem): number => {
|
||||
if (item.width && item.height) {
|
||||
return item.width / item.height;
|
||||
}
|
||||
return 16 / 9; // Default aspect ratio
|
||||
};
|
||||
|
||||
export const useMediaStore = create<MediaStore>((set, get) => ({
|
||||
mediaItems: [],
|
||||
isLoading: false,
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { create } from "zustand";
|
||||
import type { TrackType } from "@/types/timeline";
|
||||
import { useEditorStore } from "./editor-store";
|
||||
import { useMediaStore } from "./media-store";
|
||||
import { toast } from "sonner";
|
||||
import { useMediaStore, getMediaAspectRatio } from "./media-store";
|
||||
|
||||
// Helper function to manage clip naming with suffixes
|
||||
const getClipNameWithSuffix = (
|
||||
@ -232,7 +231,9 @@ export const useTimelineStore = create<TimelineStore>((set, get) => ({
|
||||
(mediaItem.type === "image" || mediaItem.type === "video")
|
||||
) {
|
||||
const editorStore = useEditorStore.getState();
|
||||
editorStore.setCanvasSizeFromAspectRatio(mediaItem.aspectRatio);
|
||||
editorStore.setCanvasSizeFromAspectRatio(
|
||||
getMediaAspectRatio(mediaItem)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user