diff --git a/src/app/api/generate/providers/__tests__/popiserver.test.ts b/src/app/api/generate/providers/__tests__/popiserver.test.ts index 4ce538ab..0091e327 100644 --- a/src/app/api/generate/providers/__tests__/popiserver.test.ts +++ b/src/app/api/generate/providers/__tests__/popiserver.test.ts @@ -106,10 +106,10 @@ describe("popiserver generation provider", () => { aiModelCode: "viduq2-pro", aiModelCodeAlias: "viduq2-pro", ratio: "16:9", + aspectRatio: "16:9", resolution: "720", videoRatio: 10, }); - expect(body.aspectRatio).toBeUndefined(); }); it("returns the prepared PopiServer task request when gateway skip is enabled", async () => { @@ -316,8 +316,8 @@ describe("popiserver generation provider", () => { const body = JSON.parse(String(init?.body)); expect(body).toMatchObject({ aspect_ratio: "9:16", + aspectRatio: "9:16", }); - expect(body.aspectRatio).toBeUndefined(); }); it("embeds ratio and resolution in chatPrompt for gpt-image-2-vip", async () => { @@ -357,6 +357,7 @@ describe("popiserver generation provider", () => { expect(body).toMatchObject({ chatPrompt: "比例:16:9\n清晰度:1K\n提示词:create a cinematic cat", ratio: "16:9", + aspectRatio: "16:9", resolution: "1K", }); }); @@ -398,9 +399,9 @@ describe("popiserver generation provider", () => { expect(body).toMatchObject({ chatPrompt: "比例:9:16\n清晰度:2K\n提示词:create a clean product render", ratio: "9:16", + aspectRatio: "9:16", resolution: "2K", }); - expect(body.aspectRatio).toBeUndefined(); }); it("uses frontend referenceSubjectList for image tasks", async () => { diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index e42b35c5..e56cdb46 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -418,38 +418,6 @@ const getNodeDimensions = (node: Node): { width: number; height: number } => { }; }; -const hasAutoSizedMediaContent = (node: Node): boolean => { - const data = (node.data ?? {}) as Record; - switch (node.type) { - case "imageInput": - case "smartImage": - return Boolean(data.image || data.outputImage); - case "videoInput": - case "smartVideo": - return Boolean(data.video || data.previewVideoPoster || data.outputVideo); - case "nanoBanana": - return Boolean(data.outputImage); - case "generateVideo": - return Boolean(data.outputVideo); - default: - return false; - } -}; - -const stripNodeSizeForAutoMedia = (node: Node): Node => { - if (!hasAutoSizedMediaContent(node)) return node; - const style = node.style as Record | undefined; - if (!style && node.width === undefined && node.height === undefined) return node; - - const { width: _width, height: _height, ...restStyle } = style ?? {}; - return { - ...node, - width: undefined, - height: undefined, - style: Object.keys(restStyle).length > 0 ? restStyle : undefined, - }; -}; - const QUICK_ADD_AFFORDANCE_OFFSET_X = 18; const QUICK_ADD_HOT_ZONE_WIDTH = 96; const QUICK_ADD_HOT_ZONE_HEIGHT = 96; @@ -1432,7 +1400,7 @@ export function WorkflowCanvas() { }); const reactFlowNodes = useMemo( - () => [...allNodes.map(stripNodeSizeForAutoMedia), ...batchNodes], + () => [...allNodes, ...batchNodes], [allNodes, batchNodes] ); diff --git a/src/utils/__tests__/generationConfig.test.ts b/src/utils/__tests__/generationConfig.test.ts index 27e4e4e7..3ec94d44 100644 --- a/src/utils/__tests__/generationConfig.test.ts +++ b/src/utils/__tests__/generationConfig.test.ts @@ -421,6 +421,7 @@ describe("generationConfig", () => { subType: POPI_VIDEO_SUBTYPE_IMAGE_TO_VIDEO, referenceSubjectList: [], parameters: { + ratio: "16:9", resolution: "720p", duration: 4, videoRatio: 20, @@ -440,6 +441,8 @@ describe("generationConfig", () => { chatPrompt: "prompt", origin: "canvas", aiModelName: "Popi Video", + ratio: "16:9", + aspectRatio: "16:9", resolution: "720p", duration: 4, videoRatio: 20, diff --git a/src/utils/popiserverTaskPayload.ts b/src/utils/popiserverTaskPayload.ts index 402f6df2..8c880155 100644 --- a/src/utils/popiserverTaskPayload.ts +++ b/src/utils/popiserverTaskPayload.ts @@ -64,6 +64,12 @@ function resolveAspectRatio(parameters: Record | undefined): st return asString(parameters?.ratio) ?? asString(parameters?.aspectRatio) ?? asString(parameters?.aspect_ratio) ?? ""; } +function mapRatioToAspectRatio(parameters: Record): Record { + if (asString(parameters.aspectRatio)) return parameters; + const aspectRatio = asString(parameters.ratio) ?? asString(parameters.aspect_ratio); + return aspectRatio ? { ...parameters, aspectRatio } : parameters; +} + function needsPromptEmbeddedParameters(modelCode: string, modelAlias: string): boolean { return ( modelCode === "gpt-image-2-vip" || @@ -105,7 +111,7 @@ export function buildPopiTaskBody( const rawParameters = removeLegacyAudioParameters(input.parameters || {}); const rawExtraTaskParams = removeLegacyAudioParameters(input.extraTaskParams || {}); const aspectRatio = resolveAspectRatio(rawParameters); - const parameters = rawParameters; + const parameters = mapRatioToAspectRatio(rawParameters); const selectedModel = { provider: "popiserver" as const, modelId: input.model.id,