fix: align krea seedance video payload

This commit is contained in:
Your Name 2026-04-15 20:42:28 +08:00
parent 8e51697800
commit bc8c3084fe
2 changed files with 54 additions and 5 deletions

View File

@ -78,6 +78,9 @@ function createImageConfig(fields: string[]) {
}
function createVideoDurationOptions(modelId: string) {
if (modelId.includes("/bytedance/seedance-2")) {
return Array.from({ length: 12 }, (_, index) => index + 4);
}
if (modelId.includes("/minimax/hailuo-02") || modelId.includes("/minimax/hailuo-2.3")) {
return [6, 10];
}
@ -114,13 +117,18 @@ function createVideoCapabilities(modelId: string, fields: string[]) {
const durationOptions = fields.includes("duration") ? createVideoDurationOptions(modelId) : [5];
const resolutionOptions = fields.includes("resolution")
? (modelId.includes("/minimax/") ? ["720p", "1080p"] : ["480p", "720p", "1080p"])
? modelId.includes("/bytedance/seedance-2")
? ["480p", "720p"]
: (modelId.includes("/minimax/") ? ["720p", "1080p"] : ["480p", "720p", "1080p"])
: ["720p"];
const ratioOptions = modelId.includes("/bytedance/seedance-2")
? ["16:9", "9:16"]
: ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
return {
supportedModes: Array.from(supportedModes),
supportedResolutions: resolutionOptions,
supportedRatios: ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"],
supportedRatios: ratioOptions,
durationRange: {
min: Math.min(...durationOptions),
max: Math.max(...durationOptions),

View File

@ -325,6 +325,9 @@ function normalizeBatchSize(value?: number) {
function normalizeVideoDuration(duration: unknown, endpoint: string) {
const value = Number.isFinite(Number(duration)) ? Math.round(Number(duration)) : 5;
if (endpoint.includes("/bytedance/seedance-2")) {
return clamp(value || 5, 4, 15);
}
if (endpoint.includes("/minimax/hailuo-02") || endpoint.includes("/minimax/hailuo-2.3")) {
return clamp(value || 6, 6, 10);
}
@ -345,6 +348,9 @@ function normalizeVideoDuration(duration: unknown, endpoint: string) {
function normalizeVideoResolution(resolution: unknown, endpoint: string) {
const normalized = normalizeText(String(resolution || "")).toLowerCase();
if (endpoint.includes("/bytedance/seedance-2")) {
return normalized === "480p" ? "480p" : "720p";
}
if (endpoint.includes("/minimax/")) {
if (normalized === "1080p") return "1080p";
if (normalized === "512p" || normalized === "480p") return "512p";
@ -356,6 +362,9 @@ function normalizeVideoResolution(resolution: unknown, endpoint: string) {
function normalizeVideoAspectRatio(ratio: unknown, endpoint: string) {
const normalized = normalizeAspectRatio(String(ratio || ""), "16:9");
if (endpoint.includes("/bytedance/seedance-2")) {
return normalized === "9:16" ? "9:16" : "16:9";
}
if (endpoint.includes("/openai/sora-2")) {
return normalized === "9:16" ? "9:16" : "16:9";
}
@ -728,6 +737,11 @@ async function requestKreaJob(
if (!jobId) {
throw new Error("Krea 未返回任务 ID");
}
console.log("[Krea] Job accepted:", {
endpoint,
jobId,
status: normalizeText(payload?.status) || null,
});
return { ...payload, job_id: jobId };
}
@ -771,6 +785,12 @@ async function waitForKreaJob(
return payload;
}
if (status === "failed" || status === "cancelled") {
console.error("[Krea] Job failed:", {
jobId,
kind,
status,
response: stringifyForLog(payload),
});
throw new Error(String(payload?.error || payload?.message || "Krea 任务失败"));
}
@ -821,6 +841,15 @@ function buildKreaBody(params: {
const required = new Set(requiredFields);
const body: Record<string, any> = {};
const isVideo = kind === "video";
const videoMode =
isVideo
? videoParams?.mode ||
(imageUrls.length > 1
? "first-last-frame"
: imageUrls.length > 0
? "first-frame"
: "text-to-video")
: undefined;
const hasImageReference =
kind !== "video" && imageUrls.length > 0 && hasKreaSourceImageField(fields);
const requestedImageAspectRatio = normalizeText(imageParams?.aspectRatio).toLowerCase();
@ -914,14 +943,26 @@ function buildKreaBody(params: {
body.characterReferenceImages = imageUrls.slice(0, 4);
}
if (fields.has("referenceImages") && imageUrls.length > 0) {
if (
fields.has("referenceImages") &&
imageUrls.length > 0 &&
(!isVideo || videoMode === "reference-images")
) {
body.referenceImages = endpoint.includes("/image/runway/gen-4-image")
? buildTaggedReferences(imageUrls, "ref", 3)
: imageUrls.slice(0, endpoint.includes("/seedance-2") ? 9 : 4);
}
if (fields.has("startImage") && imageUrls[0]) body.startImage = imageUrls[0];
if (fields.has("endImage") && imageUrls[1]) body.endImage = imageUrls[1];
if (
fields.has("startImage") &&
imageUrls[0] &&
(!isVideo || videoMode === "first-frame" || videoMode === "first-last-frame")
) {
body.startImage = imageUrls[0];
}
if (fields.has("endImage") && imageUrls[1] && (!isVideo || videoMode === "first-last-frame")) {
body.endImage = imageUrls[1];
}
if (fields.has("init_image_url") && imageUrls[0]) body.init_image_url = imageUrls[0];
if (fields.has("references") && imageUrls[0]) {
body.references = [{ type: "image", uri: imageUrls[0] }];