From 87ff9970208eb8eede704fc5638f4a5fe54d2918 Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Thu, 20 Aug 2026 23:43:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(*):=20MiniMax=20=E8=A7=86=E9=A2=91=E8=83=BD?= =?UTF-8?q?=E5=8A=9B=20-=20=E6=94=BE=E8=A1=8C=E5=8F=82=E8=80=83=E7=B4=A0?= =?UTF-8?q?=E6=9D=90=E8=A7=86=E9=A2=91=E7=94=9F=E6=88=90=E5=B9=B6=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E6=93=8D=E4=BD=9C=E6=8E=A8=E5=AF=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/service/model_capability.go | 1 + backend/internal/service/model_capability_test.go | 10 ++++++++++ web/src/lib/model-capabilities.ts | 1 + web/src/lib/model-selection.ts | 6 +++--- web/src/services/api/generation-task.ts | 12 ++++++++---- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/backend/internal/service/model_capability.go b/backend/internal/service/model_capability.go index 9769bd6c3..8a052a933 100644 --- a/backend/internal/service/model_capability.go +++ b/backend/internal/service/model_capability.go @@ -229,6 +229,7 @@ func DefaultModelCapabilityConfigForModel(protocol string, modelName string) *Mo video.Resolutions = []string{"1080p"} video.DefaultResolution = "1080p" case model.ChannelInterfaceMiniMaxVideo: + video.Operations = append(video.Operations, "reference_to_video") video.References.MaxImages = 9 video.References.MaxImageBytes = 30 * 1024 * 1024 video.References.MaxVideos = 3 diff --git a/backend/internal/service/model_capability_test.go b/backend/internal/service/model_capability_test.go index d8d3666e2..831201a39 100644 --- a/backend/internal/service/model_capability_test.go +++ b/backend/internal/service/model_capability_test.go @@ -83,6 +83,16 @@ func TestDefaultVideoCapabilityUsesProtocolSpecificResolutionTiers(t *testing.T) } } +func TestDefaultMiniMaxVideoCapabilitySupportsReferenceGeneration(t *testing.T) { + profile := DefaultModelCapabilityConfigForModel("minimax-video", "MiniMax-H3") + if profile == nil || profile.Video == nil { + t.Fatal("MiniMax video profile = nil") + } + if !containsCapabilityString(profile.Video.Operations, "reference_to_video") { + t.Fatalf("operations = %v, want reference_to_video", profile.Video.Operations) + } +} + func TestCapabilitySpecFromModelCapabilityConfigRestoresLegacyWildcardImageSizes(t *testing.T) { config := &ModelCapabilityConfig{ Version: 1, diff --git a/web/src/lib/model-capabilities.ts b/web/src/lib/model-capabilities.ts index 1cb4b5013..abb984841 100644 --- a/web/src/lib/model-capabilities.ts +++ b/web/src/lib/model-capabilities.ts @@ -315,6 +315,7 @@ export function defaultModelCapabilityConfig(protocol?: ModelProtocol, model = " video.resolutions = ["768P", "2K"]; video.defaultResolution = "768P"; video.watermark = { supported: true, default: false }; + video.operations.push("reference_to_video"); } return { version: 1, text, image: defaultImageCapabilityConfig(protocol, model), video }; } diff --git a/web/src/lib/model-selection.ts b/web/src/lib/model-selection.ts index b0d0a7c91..a2d4fc093 100644 --- a/web/src/lib/model-selection.ts +++ b/web/src/lib/model-selection.ts @@ -312,14 +312,13 @@ export function modelGroupReferenceLimits(config: AiConfig, selected: string, ca export function inferVideoOperation(input: ModelInputSummary) { const visualInputCount = input.imageCount + input.characterCount; - if (input.audioCount > 0 && visualInputCount === 0 && input.videoCount === 0) return "audio_to_video"; - if (input.videoCount > 0) return "extend"; + if (input.audioCount > 0 || input.videoCount > 0 || visualInputCount > 2) return "reference_to_video"; if (visualInputCount > 0) return "image_to_video"; return "text_to_video"; } export function resolveVideoOperation(input: ModelInputSummary, storedOperation?: string) { - if (storedOperation && !["text_to_video", "image_to_video", "audio_to_video", "extend"].includes(storedOperation)) return storedOperation; + if (storedOperation && !["text_to_video", "image_to_video", "audio_to_video", "extend", "reference_to_video"].includes(storedOperation)) return storedOperation; return inferVideoOperation(input); } @@ -327,6 +326,7 @@ function videoOperationLabel(operation: string) { if (operation === "text_to_video") return "文生视频"; if (operation === "image_to_video") return "图生视频"; if (operation === "audio_to_video") return "音频生视频"; + if (operation === "reference_to_video") return "参考素材生视频"; if (operation === "extend") return "视频续写"; return "当前生成模式"; } diff --git a/web/src/services/api/generation-task.ts b/web/src/services/api/generation-task.ts index 8f63919f5..ee301818c 100644 --- a/web/src/services/api/generation-task.ts +++ b/web/src/services/api/generation-task.ts @@ -6,6 +6,7 @@ import { LOCAL_DREAMINA_WAIT_STOPPED_CODE, LocalDreaminaGenerationClientError, r import { isLocalDreaminaBackgroundTask, localDreaminaTaskId, projectLocalDreaminaTask, stripLocalDreaminaTaskPrefix } from "@/services/local-dreamina-task-projection"; import { modelCapabilityConfigFor } from "@/lib/model-capabilities"; import { grokImagePromptLimitError } from "@/lib/grok-image-prompt-limit"; +import { resolveVideoOperation } from "@/lib/model-selection"; import { modelOptionName, resolveModelChannel, resolveModelRequestConfig, type AiConfig } from "@/stores/use-config-store"; import { useLocalDreaminaModelStore } from "@/stores/use-local-dreamina-model-store"; import type { ReferenceImage } from "@/types/image"; @@ -268,10 +269,13 @@ async function runLocalDreaminaGeneration(options: BackendGenerationTaskOptions, function generationOperation(options: BackendGenerationTaskOptions) { if (options.mode !== "video") return options.mode; - const imageCount = options.referenceImages?.length ?? 0; - if ((options.referenceVideos?.length ?? 0) > 0 || (options.referenceAudios?.length ?? 0) > 0 || imageCount > 2) return "reference_to_video"; - if (imageCount > 0) return "image_to_video"; - return "text_to_video"; + return resolveVideoOperation({ + textCount: 0, + imageCount: options.referenceImages?.length ?? 0, + videoCount: options.referenceVideos?.length ?? 0, + audioCount: options.referenceAudios?.length ?? 0, + characterCount: 0, + }, options.metadata?.videoEditOperation as string | undefined); } export function isGenerationTaskCancelled(error: unknown, signal?: AbortSignal) {