fix: refresh krea image provider integration

This commit is contained in:
Your Name 2026-05-30 12:53:18 +08:00
parent 9adb55c6a7
commit fec4b9d5aa
3 changed files with 209 additions and 106 deletions

View File

@ -328,7 +328,6 @@ async function createEnhanceProJob(params: {
width: params.width, width: params.width,
height: params.height, height: params.height,
image_url: params.sourceImageUrl, image_url: params.sourceImageUrl,
batchSize: params.requestBody.batchSize,
seed: params.requestBody.seed, seed: params.requestBody.seed,
prompt: String(params.requestBody.prompt || "").trim(), prompt: String(params.requestBody.prompt || "").trim(),
output_format: params.requestBody.output_format || params.config.defaultOutputFormat, output_format: params.requestBody.output_format || params.config.defaultOutputFormat,
@ -1065,9 +1064,8 @@ export async function POST(request: NextRequest) {
config.maxOutputEdge, config.maxOutputEdge,
); );
const batchSize = config.allowBatchSize // Krea removed batch generation from the enhance endpoint.
? clampInteger(body.batchSize, 1, config.maxBatchSize, 1) const batchSize = 1;
: 1;
const upscalingActivated = body.upscaling_activated === true; const upscalingActivated = body.upscaling_activated === true;
const imageScalingFactor = clampNumber( const imageScalingFactor = clampNumber(
body.image_scaling_factor, body.image_scaling_factor,

View File

@ -27,23 +27,33 @@ const REFERENCE_INPUT_FIELDS = new Set([
"imageUrl", "imageUrl",
"imageUrls", "imageUrls",
"image_url", "image_url",
"image_urls",
"styleImages", "styleImages",
"style_images",
"imageStyleRefs", "imageStyleRefs",
"image_style_references",
"characterReferenceImages", "characterReferenceImages",
"character_reference_images",
"backgroundImage", "backgroundImage",
"referenceImages", "referenceImages",
"reference_images",
"startImage", "startImage",
"endImage", "endImage",
"init_image_url", "init_image_url",
"references", "references",
"subjects", "subjects",
"styleReferences", "styleReferences",
"style_references",
"elementReferences", "elementReferences",
"element_references",
"videoReference", "videoReference",
"video_reference",
"startVideo", "startVideo",
"init_video", "init_video",
"referenceVideos", "referenceVideos",
"reference_videos",
"referenceAudios", "referenceAudios",
"reference_audios",
]); ]);
function hasReferenceInput(fields: string[]) { function hasReferenceInput(fields: string[]) {
@ -68,12 +78,15 @@ function createDefaultParams(
function createImageConfig(fields: string[]) { function createImageConfig(fields: string[]) {
return { return {
maxImages: fields.includes("batchSize") ? 4 : 1, // Krea removed batch generation; one request now produces one output.
maxImages: 1,
supportsSize: fields.includes("width") && fields.includes("height"), supportsSize: fields.includes("width") && fields.includes("height"),
supports1K: true, supports1K: true,
supports2K: true, supports2K: true,
supports4K: fields.includes("resolution") || fields.includes("width"), supports4K: fields.includes("resolution") || fields.includes("width"),
supportsPromptExtend: fields.includes("skipPromptExpansion"), supportsPromptExtend:
fields.includes("skipPromptExpansion") ||
fields.includes("skip_prompt_expansion"),
supportsNegativePrompt: fields.includes("negative_prompt"), supportsNegativePrompt: fields.includes("negative_prompt"),
supportsWatermark: false, supportsWatermark: false,
supportsSeed: fields.includes("seed"), supportsSeed: fields.includes("seed"),
@ -233,62 +246,65 @@ function videoPreset(
} }
export const KREA_MODEL_PRESETS: KreaModelPreset[] = [ export const KREA_MODEL_PRESETS: KreaModelPreset[] = [
imagePreset(10, "/generate/image/bfl/flux-1-dev", "Flux", ["strength", "seed", "steps", "styleImages", "imageStyleRefs", "prompt", "width", "height", "guidance_scale_flux", "imageUrl", "relaxedModeAccess", "styles"], ["prompt"]), imagePreset(10, "/generate/image/krea/krea-2/medium", "Krea 2 Medium", ["prompt", "seed", "styles", "image_style_references", "aspect_ratio", "resolution", "creativity", "moodboards"], ["prompt", "aspect_ratio", "resolution"]),
imagePreset(20, "/generate/image/bfl/flux-1-kontext-dev", "Flux Kontext", ["strength", "seed", "steps", "styleImages", "imageStyleRefs", "prompt", "width", "height", "guidance_scale_flux", "imageUrl", "relaxedModeAccess", "styles"], ["prompt"]), imagePreset(20, "/generate/image/krea/krea-2/large", "Krea 2 Large", ["prompt", "seed", "styles", "image_style_references", "aspect_ratio", "resolution", "creativity", "moodboards"], ["prompt", "aspect_ratio", "resolution"]),
imagePreset(30, "/generate/image/google/nano-banana-pro", "Nano Banana Pro", ["batchSize", "prompt", "width", "height", "imageUrls", "aspectRatio", "styleImages", "resolution"], ["prompt"]), imagePreset(30, "/generate/image/bfl/flux-1-dev", "Flux", ["prompt", "seed", "steps", "width", "height", "image_url", "styles", "strength", "guidance_scale", "style_images", "image_style_references"], ["prompt"]),
imagePreset(40, "/generate/image/google/nano-banana-2", "Nano Banana 2", ["batchSize", "prompt", "width", "height", "imageUrls", "aspectRatio", "styleImages", "resolution"], ["prompt"]), imagePreset(40, "/generate/image/bfl/flux-1-kontext-dev", "Flux Kontext", ["prompt", "seed", "steps", "width", "height", "image_url", "strength", "guidance_scale", "style_images"], ["prompt"]),
imagePreset(50, "/generate/image/google/nano-banana", "Nano Banana", ["batchSize", "prompt", "width", "height", "imageUrls", "styleImages", "aspectRatio"], ["prompt"]), imagePreset(50, "/generate/image/google/nano-banana-pro", "Nano Banana Pro", ["prompt", "width", "height", "image_urls", "aspect_ratio", "resolution", "style_images"], ["prompt"]),
imagePreset(60, "/generate/image/bfl/flux-1.1-pro", "Flux 1.1 Pro", ["batchSize", "prompt", "width", "height", "seed"], ["prompt", "width", "height"]), imagePreset(60, "/generate/image/google/nano-banana-2", "Nano Banana 2", ["prompt", "width", "height", "image_urls", "aspect_ratio", "resolution", "style_images"], ["prompt"]),
imagePreset(70, "/generate/image/bfl/flux-1.1-pro-ultra", "Flux 1.1 Pro Ultra", ["batchSize", "prompt", "width", "height", "seed", "raw"], ["prompt"]), imagePreset(70, "/generate/image/google/nano-banana", "Nano Banana", ["prompt", "width", "height", "image_urls", "aspect_ratio", "style_images"], ["prompt"]),
imagePreset(80, "/generate/image/ideogram/ideogram-2-turbo", "Ideogram 2.0A Turbo", ["batchSize", "prompt", "width", "height", "seed"], ["prompt"]), imagePreset(80, "/generate/image/bfl/flux-1.1-pro", "Flux 1.1 Pro", ["prompt", "width", "height", "seed"], ["prompt", "width", "height"]),
imagePreset(90, "/generate/image/ideogram/ideogram-3", "Ideogram 3.0", ["batchSize", "prompt", "width", "height", "seed", "styleImages", "characterReferenceImages"], ["prompt"]), imagePreset(90, "/generate/image/bfl/flux-1.1-pro-ultra", "Flux 1.1 Pro Ultra", ["prompt", "width", "height", "seed", "raw"], ["prompt"]),
imagePreset(100, "/generate/image/google/imagen-3", "Imagen 3", ["batchSize", "prompt", "width", "height", "seed"], ["prompt"]), imagePreset(100, "/generate/image/ideogram/ideogram-2-turbo", "Ideogram 2.0A Turbo", ["prompt", "width", "height", "seed"], ["prompt"]),
imagePreset(110, "/generate/image/google/imagen-4", "Imagen 4", ["batchSize", "prompt", "width", "height", "seed"], ["prompt"]), imagePreset(110, "/generate/image/ideogram/ideogram-3", "Ideogram 3.0", ["prompt", "width", "height", "seed", "character_reference_images", "style_images"], ["prompt"]),
imagePreset(120, "/generate/image/google/imagen-4-fast", "Imagen 4 Fast", ["batchSize", "prompt", "width", "height", "seed"], ["prompt"]), imagePreset(120, "/generate/image/google/imagen-3", "Imagen 3", ["prompt", "width", "height", "seed"], ["prompt"]),
imagePreset(130, "/generate/image/google/imagen-4-ultra", "Imagen 4 Ultra", ["batchSize", "prompt", "width", "height", "seed"], ["prompt"]), imagePreset(130, "/generate/image/google/imagen-4", "Imagen 4", ["prompt", "width", "height", "seed"], ["prompt"]),
imagePreset(140, "/generate/image/runway/gen-4-image", "Runway Gen-4", ["batchSize", "prompt", "width", "height", "seed", "referenceImages"], ["prompt", "referenceImages"]), imagePreset(140, "/generate/image/google/imagen-4-fast", "Imagen 4 Fast", ["prompt", "width", "height", "seed"], ["prompt"]),
imagePreset(150, "/generate/image/openai/gpt-image", "ChatGPT Image", ["batchSize", "prompt", "width", "height", "quality", "backgroundImage", "imageUrls", "styleImages", "styles"], ["prompt"]), imagePreset(150, "/generate/image/google/imagen-4-ultra", "Imagen 4 Ultra", ["prompt", "width", "height", "seed"], ["prompt"]),
imagePreset(160, "/generate/image/bytedance/seedream-3", "Seedream 3", ["batchSize", "prompt", "width", "height", "seed", "model"], ["prompt", "model"]), imagePreset(160, "/generate/image/runway/gen-4-image", "Runway Gen-4", ["prompt", "width", "height", "seed", "reference_images"], ["prompt", "reference_images"]),
imagePreset(170, "/generate/image/bytedance/seedream-4", "Seedream 4", ["batchSize", "prompt", "seed", "width", "height", "styleImages"], ["prompt", "width", "height"]), imagePreset(170, "/generate/image/openai/gpt-image", "ChatGPT Image", ["prompt", "width", "height", "quality", "image_urls", "styles", "style_images"], ["prompt"]),
imagePreset(180, "/generate/image/bytedance/seedream-5-lite", "Seedream 5 Lite", ["batchSize", "prompt", "seed", "width", "height", "styleImages"], ["prompt", "width", "height"]), imagePreset(180, "/generate/image/openai/gpt-image-2", "ChatGPT Image 2", ["prompt", "quality", "image_urls", "width", "height", "aspect_ratio", "resolution", "style_images"], ["prompt"]),
imagePreset(190, "/generate/image/qwen/2512", "Qwen 2512", ["prompt", "negative_prompt", "width", "height", "num_inference_steps", "cfg_scale", "seed", "batchSize", "skipPromptExpansion", "styles"], ["prompt"]), imagePreset(190, "/generate/image/luma/uni-1", "Luma Uni 1", ["prompt", "width", "height", "mode", "style", "output_format", "web_search", "style_images"], ["prompt"]),
imagePreset(200, "/generate/image/z-image/z-image", "Z Image", ["prompt", "width", "height", "batchSize", "seed", "imageUrl", "denoising_strength", "styleImages", "skipPromptExpansion", "styles"], ["prompt", "width", "height"]), imagePreset(200, "/generate/image/bytedance/seedream-4", "Seedream 4", ["prompt", "width", "height", "seed", "style_images"], ["prompt", "width", "height"]),
imagePreset(210, "/generate/image/bytedance/seededit", "SeedEdit", ["batchSize", "prompt", "seed", "imageUrl"], ["prompt", "imageUrl"]), imagePreset(210, "/generate/image/bytedance/seedream-5-lite", "Seedream 5 Lite", ["prompt", "width", "height", "seed", "style_images"], ["prompt", "width", "height"]),
enhancePreset(220, "/generate/enhance/topaz/generative-enhance", "Topaz Generative", ["batchSize", "width", "height", "seed", "prompt", "output_format", "subject_detection", "face_enhancement", "face_enhancement_creativity", "face_enhancement_strength", "crop_to_fill", "image_url", "model", "upscaling_activated", "image_scaling_factor", "creativity", "texture", "sharpen", "denoise", "detail"], ["width", "height", "image_url"]), imagePreset(220, "/generate/image/qwen/2512", "Qwen 2512", ["prompt", "negative_prompt", "width", "height", "num_inference_steps", "cfg_scale", "seed", "skip_prompt_expansion", "styles"], ["prompt"]),
enhancePreset(230, "/generate/enhance/topaz/standard-enhance", "Topaz", ["batchSize", "width", "height", "seed", "prompt", "output_format", "subject_detection", "face_enhancement", "face_enhancement_creativity", "face_enhancement_strength", "crop_to_fill", "image_url", "model", "upscaling_activated", "image_scaling_factor", "sharpen", "denoise", "fix_compression", "strength"], ["width", "height", "image_url", "model"]), imagePreset(230, "/generate/image/z-image/z-image", "Z Image", ["prompt", "seed", "denoising_strength", "styles", "skip_prompt_expansion", "aspect_ratio", "resolution", "image_url", "style_images"], ["prompt", "aspect_ratio", "resolution"]),
enhancePreset(240, "/generate/enhance/topaz/bloom-enhance", "Topaz Bloom", ["batchSize", "width", "height", "seed", "prompt", "output_format", "crop_to_fill", "image_url", "model", "creativity", "face_preservation", "color_preservation", "upscaling_activated", "image_scaling_factor"], ["width", "height", "image_url", "model"]), imagePreset(240, "/generate/image/bytedance/seededit", "SeedEdit", ["prompt", "seed", "image_url"], ["prompt", "image_url"]),
videoPreset(250, "/generate/video/kling/kling-1", "Kling 1.0", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage", "mode"], ["prompt"]), enhancePreset(250, "/generate/enhance/topaz/generative-enhance", "Topaz Generative", ["prompt", "width", "height", "seed", "image_url", "model", "output_format", "subject_detection", "face_enhancement", "face_enhancement_creativity", "face_enhancement_strength", "crop_to_fill", "upscaling_activated", "image_scaling_factor", "creativity", "texture", "sharpen", "denoise", "detail"], ["width", "height", "image_url"]),
videoPreset(260, "/generate/video/kling/kling-1.5", "Kling 1.5", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage"], ["prompt"]), enhancePreset(260, "/generate/enhance/topaz/standard-enhance", "Topaz", ["prompt", "width", "height", "seed", "image_url", "model", "output_format", "subject_detection", "face_enhancement", "face_enhancement_creativity", "face_enhancement_strength", "crop_to_fill", "upscaling_activated", "image_scaling_factor", "sharpen", "denoise", "fix_compression", "strength"], ["width", "height", "image_url", "model"]),
videoPreset(270, "/generate/video/kling/kling-1.6", "Kling 1.6", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage", "mode"], ["prompt"]), enhancePreset(270, "/generate/enhance/topaz/bloom-enhance", "Topaz Bloom", ["prompt", "width", "height", "seed", "image_url", "output_format", "crop_to_fill", "creativity", "face_preservation", "color_preservation", "upscaling_activated", "image_scaling_factor"], ["width", "height", "image_url"]),
videoPreset(280, "/generate/video/kling/kling-2", "Kling 2.0", ["startImage", "prompt", "aspectRatio", "endImage", "mode"], ["prompt"]), videoPreset(280, "/generate/video/kling/kling-1", "Kling 1.0", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage", "mode"], ["prompt"]),
videoPreset(290, "/generate/video/kling/kling-2.1", "Kling 2.1", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "mode"], ["prompt"]), videoPreset(290, "/generate/video/kling/kling-1.5", "Kling 1.5", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage"], ["prompt"]),
videoPreset(300, "/generate/video/kling/kling-2.5", "Kling 2.5", ["startImage", "prompt", "aspectRatio", "duration", "endImage"], ["prompt"]), videoPreset(300, "/generate/video/kling/kling-1.6", "Kling 1.6", ["startImage", "prompt", "aspectRatio", "duration", "cameraControl", "endImage", "mode"], ["prompt"]),
videoPreset(310, "/generate/video/kling/kling-2.6", "Kling 2.6", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "generateAudio"], ["prompt"]), videoPreset(310, "/generate/video/kling/kling-2", "Kling 2.0", ["startImage", "prompt", "aspectRatio", "endImage", "mode"], ["prompt"]),
videoPreset(320, "/generate/video/kling/kling-o1", "Kling o1", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "styleReferences", "elementReferences", "videoReference"], ["prompt"]), videoPreset(320, "/generate/video/kling/kling-2.1", "Kling 2.1", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "mode"], ["prompt"]),
videoPreset(330, "/generate/video/minimax/hailuo", "Hailuo", ["startImage", "prompt", "expandPrompt", "cameraControl", "model", "subjects"], ["prompt"]), videoPreset(330, "/generate/video/kling/kling-2.5", "Kling 2.5", ["startImage", "prompt", "aspectRatio", "duration", "endImage"], ["prompt"]),
videoPreset(340, "/generate/video/minimax/hailuo-02", "Hailuo 02", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]), videoPreset(340, "/generate/video/kling/kling-2.6", "Kling 2.6", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "generateAudio"], ["prompt"]),
videoPreset(350, "/generate/video/minimax/hailuo-2.3", "Hailuo 2.3", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]), videoPreset(350, "/generate/video/kling/kling-o1", "Kling o1", ["startImage", "prompt", "aspectRatio", "duration", "endImage", "styleReferences", "elementReferences", "videoReference"], ["prompt"]),
videoPreset(360, "/generate/video/minimax/hailuo-2.3-fast", "Hailuo 2.3 Fast", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]), videoPreset(360, "/generate/video/minimax/hailuo", "Hailuo", ["startImage", "prompt", "expandPrompt", "cameraControl", "model", "subjects"], ["prompt"]),
videoPreset(370, "/generate/video/alibaba/wan-2.1", "Wan 2.1", ["startImage", "prompt", "width", "height", "endImage", "aspectRatio", "frame_num", "styles"], ["prompt", "width", "height"]), videoPreset(370, "/generate/video/minimax/hailuo-02", "Hailuo 02", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]),
videoPreset(380, "/generate/video/alibaba/wan-2.2", "Wan 2.2", ["startImage", "guide_scale", "prompt", "width", "height", "aspectRatio", "frame_num", "styles"], ["prompt", "width", "height"]), videoPreset(380, "/generate/video/minimax/hailuo-2.3", "Hailuo 2.3", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]),
videoPreset(390, "/generate/video/alibaba/wan-2.5", "Wan 2.5", ["startImage", "prompt", "aspectRatio", "resolution", "enablePromptExpansion", "duration", "seed", "audio_url", "generateAudio"], ["prompt"]), videoPreset(390, "/generate/video/minimax/hailuo-2.3-fast", "Hailuo 2.3 Fast", ["startImage", "prompt", "expandPrompt", "endImage", "resolution", "duration"], ["prompt"]),
videoPreset(400, "/generate/video/google/veo-2", "Veo 2", ["startImage", "prompt", "aspectRatio", "duration", "image_url"], ["prompt"]), videoPreset(400, "/generate/video/alibaba/wan-2.1", "Wan 2.1", ["startImage", "prompt", "width", "height", "endImage", "aspectRatio", "frame_num", "styles"], ["prompt", "width", "height"]),
videoPreset(410, "/generate/video/google/veo-3", "Veo 3", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution"], ["prompt"]), videoPreset(410, "/generate/video/alibaba/wan-2.2", "Wan 2.2", ["startImage", "guide_scale", "prompt", "width", "height", "aspectRatio", "frame_num", "styles"], ["prompt", "width", "height"]),
videoPreset(420, "/generate/video/google/veo-3-fast", "Veo 3 Fast", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution"], ["prompt"]), videoPreset(420, "/generate/video/alibaba/wan-2.5", "Wan 2.5", ["startImage", "prompt", "aspectRatio", "resolution", "enablePromptExpansion", "duration", "seed", "audio_url", "generateAudio"], ["prompt"]),
videoPreset(430, "/generate/video/google/veo-3.1", "Veo 3.1", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution", "endImage", "referenceImages"], ["prompt"]), videoPreset(430, "/generate/video/google/veo-2", "Veo 2", ["startImage", "prompt", "aspectRatio", "duration", "image_url"], ["prompt"]),
videoPreset(440, "/generate/video/google/veo-3.1-fast", "Veo 3.1 Fast", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution", "endImage", "referenceImages"], ["prompt"]), videoPreset(440, "/generate/video/google/veo-3", "Veo 3", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution"], ["prompt"]),
videoPreset(450, "/generate/video/google/veo-3.1-lite", "Veo 3.1 Lite", ["startImage", "prompt", "aspectRatio", "duration", "resolution", "endImage"], ["prompt"]), videoPreset(450, "/generate/video/google/veo-3-fast", "Veo 3 Fast", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution"], ["prompt"]),
videoPreset(460, "/generate/video/bytedance/seedance-1.0-lite", "Seedance Lite", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "duration", "resolution"], ["prompt"]), videoPreset(460, "/generate/video/google/veo-3.1", "Veo 3.1", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution", "endImage", "referenceImages"], ["prompt"]),
videoPreset(470, "/generate/video/bytedance/seedance-1.0-pro", "Seedance Pro", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "duration", "resolution"], ["prompt"]), videoPreset(470, "/generate/video/google/veo-3.1-fast", "Veo 3.1 Fast", ["startImage", "prompt", "aspectRatio", "duration", "generateAudio", "resolution", "endImage", "referenceImages"], ["prompt"]),
videoPreset(480, "/generate/video/bytedance/seedance-1.0-pro-fast", "Seedance Pro Fast", ["startImage", "prompt", "aspectRatio", "duration", "resolution"], ["prompt"]), videoPreset(480, "/generate/video/google/veo-3.1-lite", "Veo 3.1 Lite", ["startImage", "prompt", "aspectRatio", "duration", "resolution", "endImage"], ["prompt"]),
videoPreset(490, "/generate/video/bytedance/seedance-2", "Seedance 2.0", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "referenceVideos", "referenceAudios", "duration", "generateAudio", "resolution", "seed"], ["prompt"]), videoPreset(490, "/generate/video/bytedance/seedance-1.0-lite", "Seedance Lite", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "duration", "resolution"], ["prompt"]),
videoPreset(500, "/generate/video/bytedance/seedance-2-fast", "Seedance 2.0 Fast", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "referenceVideos", "referenceAudios", "duration", "generateAudio", "resolution", "seed"], ["prompt"]), videoPreset(500, "/generate/video/bytedance/seedance-1.0-pro", "Seedance Pro", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "duration", "resolution"], ["prompt"]),
videoPreset(510, "/generate/video/openai/sora-2", "Sora 2", ["startImage", "prompt", "duration", "aspectRatio"], ["prompt"]), videoPreset(510, "/generate/video/bytedance/seedance-1.0-pro-fast", "Seedance Pro Fast", ["startImage", "prompt", "aspectRatio", "duration", "resolution"], ["prompt"]),
videoPreset(520, "/generate/video/luma/ray-2", "Ray 2", ["startImage", "prompt", "aspectRatio", "loop", "width", "height"], ["prompt", "width", "height"]), videoPreset(520, "/generate/video/bytedance/seedance-2", "Seedance 2.0", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "referenceVideos", "referenceAudios", "duration", "generateAudio", "resolution", "seed"], ["prompt"]),
videoPreset(530, "/generate/video/runway/gen-3", "Runway Gen-3", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]), videoPreset(530, "/generate/video/bytedance/seedance-2-fast", "Seedance 2.0 Fast", ["startImage", "prompt", "aspectRatio", "endImage", "referenceImages", "referenceVideos", "referenceAudios", "duration", "generateAudio", "resolution", "seed"], ["prompt"]),
videoPreset(540, "/generate/video/runway/gen-4-video", "Runway Gen-4", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]), videoPreset(540, "/generate/video/openai/sora-2", "Sora 2", ["startImage", "prompt", "duration", "aspectRatio"], ["prompt"]),
videoPreset(550, "/generate/video/runway/gen-4.5", "Runway Gen-4.5", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]), videoPreset(550, "/generate/video/luma/ray-2", "Ray 2", ["startImage", "prompt", "aspectRatio", "loop", "width", "height"], ["prompt", "width", "height"]),
videoPreset(560, "/generate/video/runway/aleph", "Runway Aleph", ["startImage", "startVideo", "startVideoTrim", "endVideoTrim", "prompt", "init_video", "init_image_url", "references", "ratio", "seed", "contentModeration"], ["prompt", "init_video"]), videoPreset(560, "/generate/video/runway/gen-3", "Runway Gen-3", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]),
videoPreset(570, "/generate/video/runway/gen-4-video", "Runway Gen-4", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]),
videoPreset(580, "/generate/video/runway/gen-4.5", "Runway Gen-4.5", ["startImage", "prompt", "aspectRatio", "duration", "seed"], ["prompt"]),
videoPreset(590, "/generate/video/runway/aleph", "Runway Aleph", ["startImage", "startVideo", "startVideoTrim", "endVideoTrim", "prompt", "init_video", "init_image_url", "references", "ratio", "seed", "contentModeration"], ["prompt", "init_video"]),
]; ];
export function getKreaModelPresetById(modelId: string) { export function getKreaModelPresetById(modelId: string) {

View File

@ -318,11 +318,6 @@ function normalizeSeed(seed?: number) {
return clamp(Math.round(Number(seed)), 0, 4294967295); return clamp(Math.round(Number(seed)), 0, 4294967295);
} }
function normalizeBatchSize(value?: number) {
if (!Number.isFinite(Number(value))) return 1;
return clamp(Math.round(Number(value)), 1, 4);
}
function normalizeVideoDuration(duration: unknown, endpoint: string) { function normalizeVideoDuration(duration: unknown, endpoint: string) {
const value = Number.isFinite(Number(duration)) ? Math.round(Number(duration)) : 5; const value = Number.isFinite(Number(duration)) ? Math.round(Number(duration)) : 5;
if (endpoint.includes("/bytedance/seedance-2")) { if (endpoint.includes("/bytedance/seedance-2")) {
@ -387,9 +382,11 @@ function buildTaggedReferences(imageUrls: string[], tagPrefix = "ref", max = 3)
const KREA_SOURCE_IMAGE_FIELDS = new Set([ const KREA_SOURCE_IMAGE_FIELDS = new Set([
"imageUrls", "imageUrls",
"image_urls",
"imageUrl", "imageUrl",
"image_url", "image_url",
"referenceImages", "referenceImages",
"reference_images",
"init_image_url", "init_image_url",
"references", "references",
]); ]);
@ -401,6 +398,19 @@ function hasKreaSourceImageField(fields: Iterable<string>) {
return false; return false;
} }
function hasAnyKreaField(fields: Set<string>, aliases: string[]) {
return aliases.some((field) => fields.has(field));
}
function getPreferredKreaField(fields: Set<string>, aliases: string[]) {
for (const field of aliases) {
if (fields.has(field)) {
return field;
}
}
return null;
}
function buildReferencePreservingPrompt(params: { function buildReferencePreservingPrompt(params: {
endpoint: string; endpoint: string;
kind: KreaModelKind; kind: KreaModelKind;
@ -449,19 +459,26 @@ function summarizeKreaReferenceFields(body: Record<string, any>) {
for (const field of [ for (const field of [
"imageUrls", "imageUrls",
"image_urls",
"imageUrl", "imageUrl",
"image_url", "image_url",
"styleImages", "styleImages",
"style_images",
"imageStyleRefs", "imageStyleRefs",
"image_style_references",
"characterReferenceImages", "characterReferenceImages",
"character_reference_images",
"referenceImages", "referenceImages",
"reference_images",
"startImage", "startImage",
"endImage", "endImage",
"init_image_url", "init_image_url",
"references", "references",
"subjects", "subjects",
"styleReferences", "styleReferences",
"style_references",
"elementReferences", "elementReferences",
"element_references",
]) { ]) {
const value = body[field]; const value = body[field];
if (Array.isArray(value)) { if (Array.isArray(value)) {
@ -841,6 +858,7 @@ function buildKreaBody(params: {
const required = new Set(requiredFields); const required = new Set(requiredFields);
const body: Record<string, any> = {}; const body: Record<string, any> = {};
const isVideo = kind === "video"; const isVideo = kind === "video";
const isImageLike = !isVideo;
const videoMode = const videoMode =
isVideo isVideo
? videoParams?.mode || ? videoParams?.mode ||
@ -864,7 +882,6 @@ function buildKreaBody(params: {
const videoDimensions = resolveVideoDimensions(ratio, videoResolution); const videoDimensions = resolveVideoDimensions(ratio, videoResolution);
if (fields.has("prompt")) body.prompt = prompt; if (fields.has("prompt")) body.prompt = prompt;
if (fields.has("batchSize")) body.batchSize = normalizeBatchSize(imageParams?.imageCount);
if ( if (
fields.has("width") && fields.has("width") &&
@ -878,13 +895,20 @@ function buildKreaBody(params: {
) { ) {
body.height = isVideo ? videoDimensions.height : imageDimensions.height; body.height = isVideo ? videoDimensions.height : imageDimensions.height;
} }
if (fields.has("aspectRatio") && shouldInferImageGeometryFromReference && inferredReferenceAspectRatio) { const aspectRatioField = getPreferredKreaField(
body.aspectRatio = inferredReferenceAspectRatio; fields,
isImageLike ? ["aspect_ratio", "aspectRatio"] : ["aspectRatio", "aspect_ratio"]
);
if (aspectRatioField && shouldInferImageGeometryFromReference && inferredReferenceAspectRatio) {
body[aspectRatioField] = inferredReferenceAspectRatio;
} else if ( } else if (
fields.has("aspectRatio") && aspectRatioField &&
(isVideo || !shouldInferImageGeometryFromReference || required.has("aspectRatio")) (isVideo ||
!shouldInferImageGeometryFromReference ||
required.has("aspectRatio") ||
required.has("aspect_ratio"))
) { ) {
body.aspectRatio = ratio === "auto" ? "1:1" : ratio; body[aspectRatioField] = ratio === "auto" ? "1:1" : ratio;
} }
if (fields.has("ratio")) body.ratio = ratio === "auto" ? "16:9" : ratio; if (fields.has("ratio")) body.ratio = ratio === "auto" ? "16:9" : ratio;
if (fields.has("resolution")) { if (fields.has("resolution")) {
@ -896,8 +920,12 @@ function buildKreaBody(params: {
if (fields.has("negative_prompt") && imageParams?.negativePrompt) { if (fields.has("negative_prompt") && imageParams?.negativePrompt) {
body.negative_prompt = imageParams.negativePrompt; body.negative_prompt = imageParams.negativePrompt;
} }
if (fields.has("skipPromptExpansion") && typeof imageParams?.promptExtend === "boolean") { const skipPromptExpansionField = getPreferredKreaField(fields, [
body.skipPromptExpansion = !imageParams.promptExtend; "skip_prompt_expansion",
"skipPromptExpansion",
]);
if (skipPromptExpansionField && typeof imageParams?.promptExtend === "boolean") {
body[skipPromptExpansionField] = !imageParams.promptExtend;
} }
if (fields.has("enablePromptExpansion")) { if (fields.has("enablePromptExpansion")) {
body.enablePromptExpansion = true; body.enablePromptExpansion = true;
@ -908,8 +936,12 @@ function buildKreaBody(params: {
if (fields.has("duration")) { if (fields.has("duration")) {
body.duration = normalizeVideoDuration(videoParams?.duration, endpoint); body.duration = normalizeVideoDuration(videoParams?.duration, endpoint);
} }
if (fields.has("generateAudio") && typeof videoParams?.generateAudio === "boolean") { const generateAudioField = getPreferredKreaField(fields, [
body.generateAudio = videoParams.generateAudio; "generate_audio",
"generateAudio",
]);
if (generateAudioField && typeof videoParams?.generateAudio === "boolean") {
body[generateAudioField] = videoParams.generateAudio;
} }
if (fields.has("loop")) { if (fields.has("loop")) {
body.loop = false; body.loop = false;
@ -924,31 +956,65 @@ function buildKreaBody(params: {
if (fields.has("output_format")) body.output_format = "jpg"; if (fields.has("output_format")) body.output_format = "jpg";
if (fields.has("backgroundImage")) body.backgroundImage = "auto"; if (fields.has("backgroundImage")) body.backgroundImage = "auto";
if (fields.has("imageUrls") && imageUrls.length > 0) { const imageUrlsField = getPreferredKreaField(
body.imageUrls = imageUrls.slice(0, 8); fields,
} isImageLike ? ["image_urls", "imageUrls"] : ["imageUrls", "image_urls"]
if (fields.has("imageUrl") && imageUrls[0]) { );
body.imageUrl = imageUrls[0]; if (imageUrlsField && imageUrls.length > 0) {
} body[imageUrlsField] = imageUrls.slice(0, 8);
if (fields.has("image_url") && imageUrls[0]) {
body.image_url = imageUrls[0];
}
if (fields.has("styleImages") && imageUrls.length > 0 && !body.imageUrls && !body.imageUrl) {
body.styleImages = buildStyleImages(imageUrls.slice(0, 4));
}
if (fields.has("imageStyleRefs") && imageUrls.length > 1) {
body.imageStyleRefs = buildStyleImages(imageUrls.slice(1, 5));
}
if (fields.has("characterReferenceImages") && imageUrls.length > 0) {
body.characterReferenceImages = imageUrls.slice(0, 4);
} }
const imageUrlField = getPreferredKreaField(
fields,
isImageLike ? ["image_url", "imageUrl"] : ["imageUrl", "image_url"]
);
if (imageUrlField && imageUrls[0]) {
body[imageUrlField] = imageUrls[0];
}
const styleImagesField = getPreferredKreaField(
fields,
isImageLike ? ["style_images", "styleImages"] : ["styleImages", "style_images"]
);
if ( if (
fields.has("referenceImages") && styleImagesField &&
imageUrls.length > 0 &&
!hasAnyKreaField(new Set(Object.keys(body)), [
"image_urls",
"imageUrls",
"image_url",
"imageUrl",
])
) {
body[styleImagesField] = buildStyleImages(imageUrls.slice(0, 4));
}
const imageStyleReferencesField = getPreferredKreaField(fields, [
"image_style_references",
"imageStyleRefs",
]);
if (imageStyleReferencesField && imageUrls.length > 1) {
body[imageStyleReferencesField] = buildStyleImages(imageUrls.slice(1, 5));
}
const characterReferenceImagesField = getPreferredKreaField(fields, [
"character_reference_images",
"characterReferenceImages",
]);
if (characterReferenceImagesField && imageUrls.length > 0) {
body[characterReferenceImagesField] = imageUrls.slice(0, 4);
}
const referenceImagesField = getPreferredKreaField(fields, [
"reference_images",
"referenceImages",
]);
if (
referenceImagesField &&
imageUrls.length > 0 && imageUrls.length > 0 &&
(!isVideo || videoMode === "reference-images") (!isVideo || videoMode === "reference-images")
) { ) {
body.referenceImages = endpoint.includes("/image/runway/gen-4-image") body[referenceImagesField] = endpoint.includes("/image/runway/gen-4-image")
? buildTaggedReferences(imageUrls, "ref", 3) ? buildTaggedReferences(imageUrls, "ref", 3)
: imageUrls.slice(0, endpoint.includes("/seedance-2") ? 9 : 4); : imageUrls.slice(0, endpoint.includes("/seedance-2") ? 9 : 4);
} }
@ -970,27 +1036,50 @@ function buildKreaBody(params: {
if (fields.has("subjects") && imageUrls[0] && videoParams?.mode === "reference-images") { if (fields.has("subjects") && imageUrls[0] && videoParams?.mode === "reference-images") {
body.subjects = [{ type: "character", image: [imageUrls[0]] }]; body.subjects = [{ type: "character", image: [imageUrls[0]] }];
} }
if (fields.has("styleReferences") && imageUrls.length > 0) { const styleReferencesField = getPreferredKreaField(fields, [
body.styleReferences = buildTaggedReferences(imageUrls, "style", 3); "style_references",
"styleReferences",
]);
if (styleReferencesField && imageUrls.length > 0) {
body[styleReferencesField] = buildTaggedReferences(imageUrls, "style", 3);
} }
if (fields.has("elementReferences") && imageUrls.length > 0) {
body.elementReferences = [ const elementReferencesField = getPreferredKreaField(fields, [
"element_references",
"elementReferences",
]);
if (elementReferencesField && imageUrls.length > 0) {
body[elementReferencesField] = [
{ {
tag: "element_1", tag: "element_1",
images: imageUrls.slice(0, 3), images: imageUrls.slice(0, 3),
}, },
]; ];
} }
if (fields.has("videoReference") && videoUrls[0]) {
body.videoReference = { url: videoUrls[0], tag: "video_1" }; const videoReferenceField = getPreferredKreaField(fields, [
"video_reference",
"videoReference",
]);
if (videoReferenceField && videoUrls[0]) {
body[videoReferenceField] = { url: videoUrls[0], tag: "video_1" };
} }
if (fields.has("startVideo") && videoUrls[0]) body.startVideo = videoUrls[0]; if (fields.has("startVideo") && videoUrls[0]) body.startVideo = videoUrls[0];
if (fields.has("init_video") && videoUrls[0]) body.init_video = videoUrls[0]; if (fields.has("init_video") && videoUrls[0]) body.init_video = videoUrls[0];
if (fields.has("referenceVideos") && videoUrls.length > 0) {
body.referenceVideos = videoUrls.slice(0, 3); const referenceVideosField = getPreferredKreaField(fields, [
"reference_videos",
"referenceVideos",
]);
if (referenceVideosField && videoUrls.length > 0) {
body[referenceVideosField] = videoUrls.slice(0, 3);
} }
if (required.has("referenceImages") && !body.referenceImages) { if (
(required.has("referenceImages") || required.has("reference_images")) &&
!body.referenceImages &&
!body.reference_images
) {
throw new Error("该 Krea 模型需要至少 1 张参考图"); throw new Error("该 Krea 模型需要至少 1 张参考图");
} }
if ((required.has("imageUrl") || required.has("image_url")) && !body.imageUrl && !body.image_url) { if ((required.has("imageUrl") || required.has("image_url")) && !body.imageUrl && !body.image_url) {
@ -1038,7 +1127,7 @@ export function createKrea({ apiKey, baseURL }: KreaConfig) {
preset?.requestFields || preset?.requestFields ||
(kind === "video" (kind === "video"
? ["prompt", "aspectRatio", "duration", "startImage", "endImage", "referenceImages"] ? ["prompt", "aspectRatio", "duration", "startImage", "endImage", "referenceImages"]
: ["prompt", "width", "height", "imageUrls", "imageUrl", "batchSize"]); : ["prompt", "width", "height", "image_urls", "image_url"]);
const requiredFields = preset?.requiredFields || ["prompt"]; const requiredFields = preset?.requiredFields || ["prompt"];
const requestedImageAspectRatio = normalizeText(options.imageParams?.aspectRatio).toLowerCase(); const requestedImageAspectRatio = normalizeText(options.imageParams?.aspectRatio).toLowerCase();
const referenceAspectRatio = const referenceAspectRatio =