fix(media): 规范比例与 OpenAI 图像尺寸参数

统一过滤非 x:x 比例,避免默认值参与候选匹配或透传上游。

支持 xK 分辨率归一化,并按 Gemini、Volces 和 OpenAI 的参数规范生成上游请求;OpenAI 显式 WxH 始终保留用户原始尺寸。

验证:在独立临时 worktree 中执行 apps/api 全量 go test ./... -count=1 通过,真实 OpenAI 请求已到达上游但受本地无效凭据阻断。
This commit is contained in:
2026-07-27 23:50:17 +08:00
parent 039220c835
commit 95776c84f6
11 changed files with 1086 additions and 71 deletions
+24 -3
View File
@@ -357,16 +357,33 @@ func volcesImageBody(request Request) map[string]any {
body["seed"] = -1
}
}
if resolution := strings.TrimSpace(stringFromAny(body["resolution"])); resolution != "" {
resolution := normalizedProviderImageResolution(body["resolution"])
size := widthHeightSize(body)
if volcesImageUsesResolutionSize(request) && resolution != "" {
body["size"] = resolution
} else if size != "" {
body["size"] = size
} else if resolution != "" {
body["size"] = resolution
}
if size := widthHeightSize(body); size != "" {
body["size"] = size
for _, key := range []string{"aspect_ratio", "aspectRatio", "ratio", "resolution", "width", "height"} {
delete(body, key)
}
normalizeVolcesSequentialImageGeneration(body, request)
return body
}
func volcesImageUsesResolutionSize(request Request) bool {
modelType := firstNonEmpty(request.ModelType, request.Candidate.ModelType)
if capability, ok := request.Candidate.Capabilities[modelType].(map[string]any); ok {
if strings.EqualFold(strings.TrimSpace(stringFromAny(capability["size_param_format"])), "resolution") {
return true
}
}
model := strings.ToLower(strings.TrimSpace(upstreamModelName(request.Candidate)))
return strings.HasPrefix(model, "doubao-seedream-5-0")
}
func volcesVideoBody(request Request) map[string]any {
body := cleanProviderBody(request.Body)
body["model"] = upstreamModelName(request.Candidate)
@@ -397,6 +414,10 @@ func cleanProviderBody(body map[string]any) map[string]any {
"_gateway_target_protocol",
"_compat_provider",
"_kling_compat_version",
"platform_id",
"platformId",
"platform_model_id",
"platformModelId",
} {
delete(out, key)
}