From 531ffc6ee8404aa46ffa055526a3d26cde9c7034 Mon Sep 17 00:00:00 2001 From: wtgoku <2687861+wtgoku@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:54:42 +0800 Subject: [PATCH] Align Vidu defaults and S2V image handling with tested server behavior The server now keeps Vidu URL-based image2video requests on a valid default duration when callers omit duration, and it forwards MiniMax S2V reference images in the images[] shape expected by the deployed Hailuo adapter. Constraint: The test environment currently validates provider behavior through popiartServer binary deploys rather than waiting for broader upstream adapter rollouts Rejected: Keep the old shared 4-second default for all providers | breaks viduq3-turbo when duration is omitted Rejected: Translate S2V references into subject_reference in popiartServer | the deployed Hailuo adapter already expects top-level images and performs its own mapping Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep provider-specific video defaults and reference-shape compatibility isolated in popiartServer unless upstream adapters are upgraded in lockstep Tested: go test ./internal/server -run TestInferRouteKeyForModelRecognizesViduAsVideo|TestGenerate|TestResolve|TestSubmitMiniMaxVideoTask|TestSubmitImageToVideoTask|TestExecuteImageToImageJobUsesGenerationsPathForMiniMax|TestExecuteImageToVideoJob|TestResolveVideoReferencesSupportsImagesArray Not-tested: Full PopiNewAPI unit suite from the local checkout --- internal/server/newapi.go | 14 ++++++++------ internal/server/video_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/internal/server/newapi.go b/internal/server/newapi.go index 27356dc..249397d 100644 --- a/internal/server/newapi.go +++ b/internal/server/newapi.go @@ -825,10 +825,12 @@ func (c *newAPIClient) submitImageToVideoTask(ctx context.Context, token, modelI if err := writer.WriteField("prompt", prompt); err != nil { return "", err } - if seconds := resolveVideoDurationSeconds(input); seconds != "" { - if err := writer.WriteField("seconds", seconds); err != nil { - return "", err - } + seconds := strings.TrimSpace(resolveVideoDurationSeconds(input)) + if seconds == "" { + seconds = "4" + } + if err := writer.WriteField("seconds", seconds); err != nil { + return "", err } if size := resolveVideoSize(modelID, input, ref); size != "" { if err := writer.WriteField("size", size); err != nil { @@ -1435,7 +1437,7 @@ func filenameFromURL(rawURL, fallback string) string { func resolveVideoDurationSeconds(input map[string]any) string { if input == nil { - return "4" + return "" } for _, value := range []any{input["seconds"], input["duration_s"], input["duration"]} { switch typed := value.(type) { @@ -1462,7 +1464,7 @@ func resolveVideoDurationSeconds(input map[string]any) string { } } } - return "4" + return "" } func resolveVideoSize(modelID string, input map[string]any, ref imageEditReference) string { diff --git a/internal/server/video_test.go b/internal/server/video_test.go index 2d3262e..4b51242 100644 --- a/internal/server/video_test.go +++ b/internal/server/video_test.go @@ -138,6 +138,35 @@ func TestSubmitImageToVideoTaskUsesURLImagesForViduModels(t *testing.T) { } } +func TestSubmitImageToVideoTaskUsesViduDefaultDurationWhenUnset(t *testing.T) { + var gotBody map[string]any + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil { + t.Fatalf("decode request body: %v", err) + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"id":"task_vidu_default_duration","status":"queued"}`)) + })) + defer srv.Close() + + client := newNewAPIClient(Config{NewAPIBaseURL: srv.URL}) + taskID, err := client.submitImageToVideoTask(context.Background(), "sk-test", "viduq3-turbo", map[string]any{ + "prompt": "animate this still gently", + }, imageEditReference{ + URL: "https://media.popi.test/m/demo/reference.png", + }) + if err != nil { + t.Fatalf("submitImageToVideoTask: %v", err) + } + if taskID != "task_vidu_default_duration" { + t.Fatalf("unexpected task id: %q", taskID) + } + if gotBody["duration"] != float64(5) { + t.Fatalf("expected default vidu duration 5, got %#v", gotBody["duration"]) + } +} + func TestSubmitMiniMaxVideoTaskUsesVideoGenerationsEndpoint(t *testing.T) { var gotPath string var gotBody map[string]any