Files
lemonspace_app/lib/ai-video-models.ts
Matthias Meister ed08b976f9 feat(canvas): add video-prompt node and enhance video generation support
- Introduced a new node type "video-prompt" for AI video generation, including its integration into the canvas command palette and node template picker.
- Updated connection validation to allow connections from text nodes to video-prompt and from video-prompt to ai-video nodes.
- Enhanced error handling and messaging for video generation failures, including specific cases for provider issues.
- Added tests to validate new video-prompt functionality and connection policies.
- Updated localization files to include new labels and prompts for video-prompt and ai-video nodes.
2026-04-07 08:50:59 +02:00

110 lines
3.3 KiB
TypeScript

export type VideoModelId =
| "wan-2-2-480p"
| "wan-2-2-720p"
| "kling-std-2-1"
| "seedance-pro-1080p"
| "kling-pro-2-6";
export type VideoModelTier = "free" | "starter" | "pro";
export type VideoModelDurationSeconds = 5 | 10;
export interface VideoModel {
id: VideoModelId;
label: string;
tier: VideoModelTier;
freepikEndpoint: string;
statusEndpointPath: string;
creditCost: Record<VideoModelDurationSeconds, number>;
supportsAudio: boolean;
supportsImageToVideo: boolean;
description: string;
}
export const VIDEO_MODELS = {
"wan-2-2-480p": {
id: "wan-2-2-480p",
label: "WAN 2.2 480p",
tier: "free",
freepikEndpoint: "/v1/ai/text-to-video/wan-2-5-t2v-720p",
statusEndpointPath: "/v1/ai/text-to-video/wan-2-5-t2v-720p/{task-id}",
creditCost: { 5: 28, 10: 56 },
supportsAudio: false,
supportsImageToVideo: false,
description: "Schnell und guenstig - gut fuer Konzepte",
},
"wan-2-2-720p": {
id: "wan-2-2-720p",
label: "WAN 2.2 720p",
tier: "free",
freepikEndpoint: "/v1/ai/text-to-video/wan-2-5-t2v-720p",
statusEndpointPath: "/v1/ai/text-to-video/wan-2-5-t2v-720p/{task-id}",
creditCost: { 5: 52, 10: 104 },
supportsAudio: false,
supportsImageToVideo: false,
description: "HD-Qualitaet, offenes Modell",
},
"kling-std-2-1": {
id: "kling-std-2-1",
label: "Kling Standard 2.1",
tier: "starter",
freepikEndpoint: "/v1/ai/image-to-video/kling-v2-1-std",
statusEndpointPath: "/v1/ai/image-to-video/kling-v2-1/{task-id}",
creditCost: { 5: 50, 10: 100 },
supportsAudio: false,
supportsImageToVideo: true,
description: "Realistisch, stabile Bewegung",
},
"seedance-pro-1080p": {
id: "seedance-pro-1080p",
label: "Seedance Pro 1080p",
tier: "starter",
freepikEndpoint: "/v1/ai/video/seedance-1-5-pro-1080p",
statusEndpointPath: "/v1/ai/video/seedance-1-5-pro-1080p/{task-id}",
creditCost: { 5: 33, 10: 66 },
supportsAudio: false,
supportsImageToVideo: false,
description: "Full-HD, gutes Preis-Leistungs-Verhaeltnis",
},
"kling-pro-2-6": {
id: "kling-pro-2-6",
label: "Kling Pro 2.6",
tier: "pro",
freepikEndpoint: "/v1/ai/image-to-video/kling-v2-6-pro",
statusEndpointPath: "/v1/ai/image-to-video/kling-v2-6/{task-id}",
creditCost: { 5: 59, 10: 118 },
supportsAudio: false,
supportsImageToVideo: true,
description: "Beste Qualitaet, cineastische Bewegung",
},
} as const satisfies Record<VideoModelId, VideoModel>;
export const DEFAULT_VIDEO_MODEL_ID: VideoModelId = "wan-2-2-720p";
const VIDEO_MODEL_IDS = Object.keys(VIDEO_MODELS) as VideoModelId[];
const VIDEO_MODEL_ID_SET = new Set<VideoModelId>(VIDEO_MODEL_IDS);
export function isVideoModelId(value: string): value is VideoModelId {
return VIDEO_MODEL_ID_SET.has(value as VideoModelId);
}
export function getVideoModel(id: string): VideoModel | undefined {
if (!isVideoModelId(id)) {
return undefined;
}
return VIDEO_MODELS[id];
}
const VIDEO_MODEL_TIER_ORDER: Record<VideoModelTier, number> = {
free: 0,
starter: 1,
pro: 2,
};
export function getAvailableVideoModels(tier: VideoModelTier): VideoModel[] {
const maxTier = VIDEO_MODEL_TIER_ORDER[tier];
return VIDEO_MODEL_IDS.map((id) => VIDEO_MODELS[id]).filter(
(model) => VIDEO_MODEL_TIER_ORDER[model.tier] <= maxTier,
);
}