diff --git a/src/app/api/generate/image/route.ts b/src/app/api/generate/image/route.ts index fd0970a..4cbd051 100644 --- a/src/app/api/generate/image/route.ts +++ b/src/app/api/generate/image/route.ts @@ -409,6 +409,15 @@ function extractImagesFromGenerationsResponse(data: Record): st } else if (typeof data.image_url === 'string') { images.push(data.image_url); } + + const streamEvents = data.__streamEvents; + if (Array.isArray(streamEvents)) { + for (const event of streamEvents) { + if (!event || typeof event !== 'object' || Array.isArray(event)) continue; + images.push(...extractImagesFromGenerationsResponse(event as Record)); + } + } + return images; } @@ -511,6 +520,7 @@ async function tryEditsWithFormData( const textFields: Record = { model, prompt, + stream: 'true', }; if (size) textFields.size = size; if (count > 1) textFields.n = String(count); @@ -700,7 +710,7 @@ async function customApiImageToImage( const chatUrl = deriveChatCompletionsUrl(endpoint); const chatBody: Record = { model: customApiConfig.modelName, - stream: false, + stream: true, messages: [ { role: 'user', @@ -734,6 +744,7 @@ async function customApiImageToImage( n: count, size: size || '1024x1024', response_format: 'b64_json', + stream: true, init_image: rawBase64, denoising_strength: denoisingStrength, }; @@ -871,6 +882,7 @@ export async function POST(request: NextRequest) { n, size: size || '1024x1024', response_format: 'b64_json', + stream: true, }; if (negativePrompt) { requestBody.negative_prompt = negativePrompt; @@ -889,6 +901,7 @@ export async function POST(request: NextRequest) { '| size:', requestBody.size, '| n:', requestBody.n, '| aspect_ratio:', requestBody.aspect_ratio, + '| stream:', requestBody.stream, '| guidance_scale:', requestBody.guidance_scale, '| prompt_length:', prompt.length, '| augmented_prompt_length:', augmentedPrompt.length); diff --git a/src/lib/custom-api-fetch.ts b/src/lib/custom-api-fetch.ts index a34a868..5a65556 100644 --- a/src/lib/custom-api-fetch.ts +++ b/src/lib/custom-api-fetch.ts @@ -273,5 +273,8 @@ export function parseCustomApiError(status: number, rawBody: string): string { if (status === 413 || /request entity too large|payload too large|content too large/i.test(trimmed)) { return '参考图请求体过大,上游模型服务拒绝接收。平台已自动压缩参考图;如果仍失败,请减少参考图数量、上传更小图片,或让 API 供应商提高图生图上传限制。'; } + if (status === 524 || /cloudflare|error code 524|a timeout occurred|origin web server timed out/i.test(trimmed)) { + return '上游 API 同步生图请求超时(Cloudflare 524)。请确认该供应商已开启流式生图或异步任务接口;高分辨率生图不要走会长时间无响应的同步接口。'; + } return trimmed || `HTTP ${status}`; }