fix: normalize video duration steps

This commit is contained in:
2026-05-13 12:29:00 +08:00
parent 2685450f3e
commit 0d0d0b9115
2 changed files with 137 additions and 15 deletions
+43 -15
View File
@@ -3,6 +3,7 @@ package runner
import (
"fmt"
"math"
"sort"
"strconv"
"strings"
@@ -518,7 +519,7 @@ func (durationProcessor) Process(params map[string]any, modelType string, contex
resolution := firstNonEmptyString(stringFromAny(params["resolution"]), context.resolution)
modeKey := videoModeKey(params)
if options := scopedNumberList(capability["duration_options"], resolution, modeKey); len(options) > 0 {
normalized := closestNumber(duration, options)
normalized := nextAllowedNumber(duration, options)
params["duration"] = normalized
syncDurationSeconds(params)
if normalized != duration {
@@ -528,7 +529,7 @@ func (durationProcessor) Process(params map[string]any, modelType string, contex
"duration",
duration,
normalized,
"duration 不在模型固定时长选项内,已调整为最近的允许值。",
"duration 不在模型固定时长选项内,已向上调整为允许值。",
capabilityPath(modelType, "duration_options"),
capability["duration_options"],
)
@@ -555,6 +556,23 @@ func (durationProcessor) Process(params map[string]any, modelType string, contex
},
)
}
return true
}
step := durationStep(capability["duration_step"], resolution, modeKey)
normalized := normalizeDurationByStep(duration, step)
params["duration"] = normalized
syncDurationSeconds(params)
if normalized != duration {
context.recordChange(
"DurationProcessor",
"adjust",
"duration",
duration,
normalized,
"duration 不符合模型时长步进,已按步进向上归一。",
capabilityPath(modelType, "duration_step"),
capability["duration_step"],
)
}
return true
}
@@ -1044,28 +1062,38 @@ func durationStep(value any, scopes ...string) float64 {
}
func normalizeDurationByRange(target float64, minValue float64, maxValue float64, step float64) float64 {
clamped := math.Min(math.Max(target, minValue), maxValue)
if step <= 0 {
return clamped
if minValue > maxValue {
minValue, maxValue = maxValue, minValue
}
snapped := math.Round((clamped-minValue)/step)*step + minValue
if step <= 0 {
step = 1
}
clamped := math.Min(math.Max(target, minValue), maxValue)
snapped := math.Ceil(((clamped-minValue)/step)-1e-9)*step + minValue
snapped = math.Min(math.Max(snapped, minValue), maxValue)
return math.Round(snapped*1_000_000) / 1_000_000
}
func closestNumber(target float64, values []float64) float64 {
func normalizeDurationByStep(target float64, step float64) float64 {
if step <= 0 {
step = 1
}
snapped := math.Ceil((target/step)-1e-9) * step
return math.Round(snapped*1_000_000) / 1_000_000
}
func nextAllowedNumber(target float64, values []float64) float64 {
if len(values) == 0 {
return target
}
closest := values[0]
minDiff := math.Abs(target - closest)
for _, value := range values[1:] {
diff := math.Abs(target - value)
if diff < minDiff {
minDiff = diff
closest = value
sorted := append([]float64(nil), values...)
sort.Float64s(sorted)
for _, value := range sorted {
if value >= target || math.Abs(value-target) < 1e-9 {
return value
}
}
return closest
return sorted[len(sorted)-1]
}
func videoModeKey(params map[string]any) string {