From cfe4b4b4e263cf3df35c8f997643b6c50a4a7aef Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Tue, 11 Aug 2026 22:54:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(canvas):=20NewAPI=20=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E7=94=9F=E6=88=90=20-=20=E6=8B=92=E7=BB=9D=E7=BC=BA=E5=B0=91?= =?UTF-8?q?=E5=8F=82=E8=80=83=E8=A7=86=E9=A2=91=E7=9A=84=E7=BA=AF=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/service/provider.go | 4 ++++ backend/internal/service/provider_test.go | 10 ++++++++++ web/src/services/api/video.ts | 1 + 3 files changed, 15 insertions(+) diff --git a/backend/internal/service/provider.go b/backend/internal/service/provider.go index 19e5dd6fb..cfa8d1dea 100644 --- a/backend/internal/service/provider.go +++ b/backend/internal/service/provider.go @@ -1724,6 +1724,10 @@ func newAPIChannel2VideoRequestBody(input canvasGenerationInput) (newAPIVideoReq if len(input.ReferenceImages) > 9 || len(input.ReferenceVideos) > 3 || len(input.ReferenceAudios) > 3 { return newAPIVideoRequest{}, errors.New("NewAPI Video Generations 最多支持 9 张参考图、3 个参考视频和 3 个参考音频") } + // NewAPI Video Generations 只接受附着在参考视频上的音频;纯音频请求会被上游拒绝。 + if len(input.ReferenceAudios) > 0 && len(input.ReferenceVideos) == 0 { + return newAPIVideoRequest{}, errors.New("NewAPI Video Generations 的参考音频必须同时提供至少 1 个参考视频;纯音频生视频请切换到支持该模式的渠道") + } modelName := strings.ToLower(strings.TrimSpace(input.Config.Model)) requiresSingleImage := modelName == "grok-video-1.5" || modelName == "grok-video-1.5-1080p" images := make([]string, 0, len(input.ReferenceImages)) diff --git a/backend/internal/service/provider_test.go b/backend/internal/service/provider_test.go index 4e0c217c9..78ee34f3e 100644 --- a/backend/internal/service/provider_test.go +++ b/backend/internal/service/provider_test.go @@ -1064,6 +1064,16 @@ func TestNewAPIChannel2SingleImageModelsRequireOneReference(t *testing.T) { } } +func TestNewAPIChannel2RejectsAudioWithoutReferenceVideo(t *testing.T) { + _, err := newAPIChannel2VideoRequestBody(canvasGenerationInput{ + Config: providerConfig{Model: "grok-image-video", VideoSeconds: "6"}, + ReferenceAudios: []providerMedia{{ID: "audio-1", URL: "https://example.com/reference.mp3"}}, + }) + if err == nil || !strings.Contains(err.Error(), "必须同时提供至少 1 个参考视频") { + t.Fatalf("newAPIChannel2VideoRequestBody() error = %v", err) + } +} + func TestNewAPIChannel2SingleImageModelUsesReferenceForStaleTextToVideoMetadata(t *testing.T) { body, err := newAPIChannel2VideoRequestBody(canvasGenerationInput{ Config: providerConfig{Model: "grok-video-1.5", VideoSeconds: "6"}, diff --git a/web/src/services/api/video.ts b/web/src/services/api/video.ts index 64d894749..d941784e1 100644 --- a/web/src/services/api/video.ts +++ b/web/src/services/api/video.ts @@ -105,6 +105,7 @@ export async function pollVideoGenerationTask(config: AiConfig, task: VideoGener async function createVideoGenerationsTask(config: ResolvedAiConfig, model: string, prompt: string, references: ReferenceImage[], videoReferences: ReferenceVideo[], audioReferences: ReferenceAudio[], options?: RequestOptions): Promise { if (references.length > 9 || videoReferences.length > 3 || audioReferences.length > 3) throw new Error("NewAPI Video Generations 最多支持 9 张参考图、3 个参考视频和 3 个参考音频"); + if (audioReferences.length > 0 && videoReferences.length === 0) throw new Error("NewAPI Video Generations 的参考音频必须同时提供至少 1 个参考视频;纯音频生视频请切换到支持该模式的渠道"); const [imageUrls, videoUrls, audioUrls] = await Promise.all([ Promise.all(references.map((item) => resolveVideoGenerationsUrl(item.url || item.dataUrl, item.storageKey))), Promise.all(videoReferences.map((item) => resolveVideoGenerationsUrl(item.url, item.storageKey))),