feat: enhance canvas functionality with scissors mode and node template updates
- Implemented visual feedback and cursor changes for scissors mode in dark and light themes, improving user interaction during edge manipulation. - Updated node template picker to include new keywords for AI image generation, enhancing searchability. - Renamed and categorized node types for clarity, including updates to asset and prompt nodes. - Added support for video nodes and adjusted related components for improved media handling on the canvas.
This commit is contained in:
81
lib/pexels-types.ts
Normal file
81
lib/pexels-types.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
export interface PexelsVideoFile {
|
||||
id: number;
|
||||
/** Pexels liefert u. a. `hls` mit `.m3u8` — nicht für `<video src>`. */
|
||||
quality: "hd" | "sd" | "uhd" | "hls";
|
||||
file_type: string;
|
||||
width: number;
|
||||
height: number;
|
||||
fps: number;
|
||||
link: string;
|
||||
}
|
||||
|
||||
export interface PexelsVideo {
|
||||
id: number;
|
||||
width: number;
|
||||
height: number;
|
||||
url: string;
|
||||
image: string;
|
||||
duration: number;
|
||||
user: {
|
||||
id: number;
|
||||
name: string;
|
||||
url: string;
|
||||
};
|
||||
video_files: PexelsVideoFile[];
|
||||
}
|
||||
|
||||
export interface VideoNodeData {
|
||||
canvasId?: string;
|
||||
pexelsId?: number;
|
||||
mp4Url?: string;
|
||||
thumbnailUrl?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
duration?: number;
|
||||
attribution?: {
|
||||
userName: string;
|
||||
userUrl: string;
|
||||
videoUrl: string;
|
||||
};
|
||||
}
|
||||
|
||||
function isProgressiveMp4Candidate(f: PexelsVideoFile): boolean {
|
||||
if (f.quality === "hls") return false;
|
||||
const url = f.link.toLowerCase();
|
||||
if (url.includes(".m3u8")) return false;
|
||||
return url.includes(".mp4");
|
||||
}
|
||||
|
||||
/**
|
||||
* Progressive MP4 für HTML5-`<video>` — niemals HLS/m3u8 (API setzt dort teils fälschlich `video/mp4`).
|
||||
*/
|
||||
export function pickVideoFile(files: PexelsVideoFile[]): PexelsVideoFile {
|
||||
const playable = files.filter(isProgressiveMp4Candidate);
|
||||
if (playable.length === 0) {
|
||||
throw new Error("Kein MP4-Download von Pexels verfügbar (nur HLS?).");
|
||||
}
|
||||
return (
|
||||
playable.find((f) => f.quality === "hd") ??
|
||||
playable.find((f) => f.quality === "uhd") ??
|
||||
playable.find((f) => f.quality === "sd") ??
|
||||
playable[0]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kleinste sinnvolle MP4 für Raster-Vorschau (bevorzugt SD, sonst kleinste Auflösung).
|
||||
*/
|
||||
export function pickPreviewVideoFile(files: PexelsVideoFile[]): PexelsVideoFile | null {
|
||||
const playable = files.filter(isProgressiveMp4Candidate);
|
||||
if (playable.length === 0) return null;
|
||||
const sd = playable.filter((f) => f.quality === "sd");
|
||||
const pool = sd.length > 0 ? sd : playable;
|
||||
return pool.reduce((best, f) => {
|
||||
const a = (f.width || 0) * (f.height || 0);
|
||||
const b = (best.width || 0) * (best.height || 0);
|
||||
if (a === 0 && b === 0) return f;
|
||||
if (a === 0) return best;
|
||||
if (b === 0) return f;
|
||||
return a < b ? f : best;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user