Browse Source

fix(seedance2): avoid sending first_frame with reference images

Kie rejects the call when both reference_image_urls and first_frame_url
(or last_frame_url) are populated — the API treats them as mutually
exclusive scene modes. Two changes:

1. kie.ts submit: skip the legacy image fallback whenever any
   schema-driven image key was already handled via dynamicInputs. The
   executor passes both `images` and `dynamicInputs`, so the fallback
   was duplicating user-provided references into first_frame_url.
2. seedance2 I2V schema: mark first_frame_url optional and note the
   mutual exclusivity in the handle descriptions so users see it in
   the node UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 3 months ago
parent
commit
2366f23cbf
  1. 7
      src/app/api/generate/providers/kie.ts
  2. 16
      src/app/api/models/[modelId]/route.ts

7
src/app/api/generate/providers/kie.ts

@ -624,9 +624,12 @@ export async function submitKieTask(
} }
} }
// Handle image inputs (fallback - only if dynamicInputs didn't already set the image key) // Handle image inputs (fallback - only if dynamicInputs didn't already handle any image key).
// If the schema-driven dynamic inputs already placed images into specific fields
// (e.g. reference_image_urls), don't also populate the default key — some models
// treat these fields as mutually exclusive and reject the request.
const imageKey = getKieImageInputKey(modelId); const imageKey = getKieImageInputKey(modelId);
if (input.images && input.images.length > 0 && !handledImageKeys.has(imageKey)) { if (input.images && input.images.length > 0 && handledImageKeys.size === 0) {
const imageUrls: string[] = []; const imageUrls: string[] = [];
for (const image of input.images) { for (const image of input.images) {
if (image.startsWith("http")) { if (image.startsWith("http")) {

16
src/app/api/models/[modelId]/route.ts

@ -881,10 +881,10 @@ function getKieSchema(modelId: string): ExtractedSchema {
], ],
inputs: [ inputs: [
{ name: "prompt", type: "text", required: false, label: "Prompt" }, { name: "prompt", type: "text", required: false, label: "Prompt" },
{ name: "first_frame_url", type: "image", required: true, label: "First Frame", description: "Starting frame of the generated video." }, { name: "first_frame_url", type: "image", required: false, label: "First Frame", description: "Starting frame. Mutually exclusive with Reference Images." },
{ name: "last_frame_url", type: "image", required: false, label: "Last Frame", description: "Optional end frame — the video interpolates between first and last." }, { name: "last_frame_url", type: "image", required: false, label: "Last Frame", description: "Optional end frame — interpolates from First to Last. Mutually exclusive with Reference Images." },
{ name: "reference_image_urls", type: "image", required: false, isArray: true, label: "Reference Images", description: "Up to 9 supplementary reference images for style/subject guidance." }, { name: "reference_image_urls", type: "image", required: false, isArray: true, label: "Reference Images", description: "Up to 9 reference images for style/subject guidance. Mutually exclusive with First/Last Frame." },
{ name: "reference_video_urls", type: "image", required: false, isArray: true, label: "Reference Videos", description: "Up to 3 reference videos (uses image handle; accepts video data URLs)." }, { name: "reference_video_urls", type: "image", required: false, isArray: true, label: "Reference Videos", description: "Up to 3 reference videos (accepts video data URLs over the image handle)." },
{ name: "reference_audio_urls", type: "audio", required: false, isArray: true, label: "Reference Audio", description: "Up to 3 reference audio clips." }, { name: "reference_audio_urls", type: "audio", required: false, isArray: true, label: "Reference Audio", description: "Up to 3 reference audio clips." },
], ],
}, },
@ -910,10 +910,10 @@ function getKieSchema(modelId: string): ExtractedSchema {
], ],
inputs: [ inputs: [
{ name: "prompt", type: "text", required: false, label: "Prompt" }, { name: "prompt", type: "text", required: false, label: "Prompt" },
{ name: "first_frame_url", type: "image", required: true, label: "First Frame", description: "Starting frame of the generated video." }, { name: "first_frame_url", type: "image", required: false, label: "First Frame", description: "Starting frame. Mutually exclusive with Reference Images." },
{ name: "last_frame_url", type: "image", required: false, label: "Last Frame", description: "Optional end frame — the video interpolates between first and last." }, { name: "last_frame_url", type: "image", required: false, label: "Last Frame", description: "Optional end frame — interpolates from First to Last. Mutually exclusive with Reference Images." },
{ name: "reference_image_urls", type: "image", required: false, isArray: true, label: "Reference Images", description: "Up to 9 supplementary reference images for style/subject guidance." }, { name: "reference_image_urls", type: "image", required: false, isArray: true, label: "Reference Images", description: "Up to 9 reference images for style/subject guidance. Mutually exclusive with First/Last Frame." },
{ name: "reference_video_urls", type: "image", required: false, isArray: true, label: "Reference Videos", description: "Up to 3 reference videos (uses image handle; accepts video data URLs)." }, { name: "reference_video_urls", type: "image", required: false, isArray: true, label: "Reference Videos", description: "Up to 3 reference videos (accepts video data URLs over the image handle)." },
{ name: "reference_audio_urls", type: "audio", required: false, isArray: true, label: "Reference Audio", description: "Up to 3 reference audio clips." }, { name: "reference_audio_urls", type: "audio", required: false, isArray: true, label: "Reference Audio", description: "Up to 3 reference audio clips." },
], ],
}, },

Loading…
Cancel
Save