diff --git a/backend/internal/service/provider.go b/backend/internal/service/provider.go index 44acf6074..3191eb950 100644 --- a/backend/internal/service/provider.go +++ b/backend/internal/service/provider.go @@ -1655,10 +1655,11 @@ func seedanceVideosBody(input canvasGenerationInput) (map[string]interface{}, er return nil, errors.New("Seedance 参考视频或参考音频需要同时连接至少 1 张主参考图") } body := map[string]interface{}{ - "model": input.Config.Model, - "prompt": seedanceVideosPromptText(input), - "aspect_ratio": normalizeSeedanceVideosRatio(input.Config.Size), - "duration": normalizeSeedanceVideosDuration(input.Config.VideoSeconds), + "model": input.Config.Model, + "prompt": seedanceVideosPromptText(input), + "aspect_ratio": normalizeSeedanceVideosRatio(input.Config.Size), + "duration": normalizeSeedanceVideosDuration(input.Config.VideoSeconds), + "generate_audio": parseBool(input.Config.VideoGenerateAudio, true), } imageURLs := make([]string, 0, len(input.ReferenceImages)) for _, image := range input.ReferenceImages { diff --git a/backend/internal/service/provider_test.go b/backend/internal/service/provider_test.go index 52a098fe7..29f7285f0 100644 --- a/backend/internal/service/provider_test.go +++ b/backend/internal/service/provider_test.go @@ -160,9 +160,10 @@ func TestSeedanceVideosBodyUsesVideosEndpointFields(t *testing.T) { body, err := seedanceVideosBody(canvasGenerationInput{ Prompt: "make it move", Config: providerConfig{ - Model: "seedance-2.0-mini-480p", - Size: "9:16", - VideoSeconds: "8", + Model: "seedance-2.0-mini-480p", + Size: "9:16", + VideoSeconds: "8", + VideoGenerateAudio: "true", }, ReferenceImages: []providerMedia{ {ID: "image-1", DataURL: testReferenceImageDataURL}, @@ -180,6 +181,9 @@ func TestSeedanceVideosBodyUsesVideosEndpointFields(t *testing.T) { if body["aspect_ratio"] != "9:16" || body["duration"] != 8 { t.Fatalf("size fields = %#v %#v", body["aspect_ratio"], body["duration"]) } + if body["generate_audio"] != true { + t.Fatalf("generate_audio = %#v, want true", body["generate_audio"]) + } if body["image_url"] != testReferenceImageDataURL { t.Fatalf("image_url = %#v", body["image_url"]) } @@ -200,6 +204,34 @@ func TestSeedanceVideosBodyUsesVideosEndpointFields(t *testing.T) { } } +func TestSeedanceVideosBodyHonorsGenerateAudio(t *testing.T) { + for _, test := range []struct { + name string + value string + want bool + }{ + {name: "default enabled", want: true}, + {name: "explicit enabled", value: "true", want: true}, + {name: "explicit disabled", value: "false", want: false}, + } { + t.Run(test.name, func(t *testing.T) { + body, err := seedanceVideosBody(canvasGenerationInput{ + Prompt: "make it move", + Config: providerConfig{ + Model: "seedance-2.0-mini-480p", + VideoGenerateAudio: test.value, + }, + }) + if err != nil { + t.Fatalf("seedanceVideosBody() error = %v", err) + } + if body["generate_audio"] != test.want { + t.Fatalf("generate_audio = %#v, want %v", body["generate_audio"], test.want) + } + }) + } +} + func TestSeedanceVideosBodyUsesOrderedFrameImageURLsWhenConfigured(t *testing.T) { body, err := seedanceVideosBody(canvasGenerationInput{ Prompt: "make it move", diff --git a/web/src/services/api/video.ts b/web/src/services/api/video.ts index e2a76470d..f9ec72ae1 100644 --- a/web/src/services/api/video.ts +++ b/web/src/services/api/video.ts @@ -225,6 +225,7 @@ async function buildSeedanceVideosPayload(config: AiConfig, model: string, promp prompt: buildSeedanceVideosPromptText(prompt, imageUrls.length, videoUrls.length, audioUrls.length), aspect_ratio: ratio === "adaptive" ? "16:9" : ratio, duration: duration < 4 ? 5 : duration, + generate_audio: boolConfig(config.videoGenerateAudio, true), ...(imageUrls[0] ? { image_url: imageUrls[0] } : {}), ...(imageUrls.length > 1 ? { reference_image_urls: imageUrls.slice(1) } : {}), ...(videoUrls.length ? { reference_videos: videoUrls } : {}),