Bound user-supplied count/duration parameters at request validation, route ratio multipliers through guarded setters, and use saturating int conversions in all quota math paths.
143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package gemini
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
|
)
|
|
|
|
// ParseVeoDurationSeconds extracts durationSeconds from metadata.
|
|
// Returns 8 (Veo default) when not specified or invalid.
|
|
func ParseVeoDurationSeconds(metadata map[string]any) int {
|
|
if metadata == nil {
|
|
return 8
|
|
}
|
|
v, ok := metadata["durationSeconds"]
|
|
if !ok {
|
|
return 8
|
|
}
|
|
switch n := v.(type) {
|
|
case float64:
|
|
if int(n) > 0 {
|
|
return int(n)
|
|
}
|
|
case int:
|
|
if n > 0 {
|
|
return n
|
|
}
|
|
}
|
|
return 8
|
|
}
|
|
|
|
// ParseVeoResolution extracts resolution from metadata.
|
|
// Returns "720p" when not specified.
|
|
func ParseVeoResolution(metadata map[string]any) string {
|
|
if metadata == nil {
|
|
return "720p"
|
|
}
|
|
v, ok := metadata["resolution"]
|
|
if !ok {
|
|
return "720p"
|
|
}
|
|
if s, ok := v.(string); ok && s != "" {
|
|
return strings.ToLower(s)
|
|
}
|
|
return "720p"
|
|
}
|
|
|
|
// ResolveVeoDuration returns the effective duration in seconds.
|
|
// Priority: metadata["durationSeconds"] > stdDuration > stdSeconds > default (8).
|
|
// The result is capped because it is used as a billing multiplier and the
|
|
// metadata path bypasses standard request validation.
|
|
func ResolveVeoDuration(metadata map[string]any, stdDuration int, stdSeconds string) int {
|
|
if metadata != nil {
|
|
if _, exists := metadata["durationSeconds"]; exists {
|
|
if d := ParseVeoDurationSeconds(metadata); d > 0 {
|
|
return min(d, relaycommon.MaxTaskDurationSeconds)
|
|
}
|
|
}
|
|
}
|
|
if stdDuration > 0 {
|
|
return min(stdDuration, relaycommon.MaxTaskDurationSeconds)
|
|
}
|
|
if s, err := strconv.Atoi(stdSeconds); err == nil && s > 0 {
|
|
return min(s, relaycommon.MaxTaskDurationSeconds)
|
|
}
|
|
return 8
|
|
}
|
|
|
|
// ResolveVeoResolution returns the effective resolution string (lowercase).
|
|
// Priority: metadata["resolution"] > SizeToVeoResolution(stdSize) > default ("720p").
|
|
func ResolveVeoResolution(metadata map[string]any, stdSize string) string {
|
|
if metadata != nil {
|
|
if _, exists := metadata["resolution"]; exists {
|
|
if r := ParseVeoResolution(metadata); r != "" {
|
|
return r
|
|
}
|
|
}
|
|
}
|
|
if stdSize != "" {
|
|
return SizeToVeoResolution(stdSize)
|
|
}
|
|
return "720p"
|
|
}
|
|
|
|
// SizeToVeoResolution converts a "WxH" size string to a Veo resolution label.
|
|
func SizeToVeoResolution(size string) string {
|
|
parts := strings.SplitN(strings.ToLower(size), "x", 2)
|
|
if len(parts) != 2 {
|
|
return "720p"
|
|
}
|
|
w, _ := strconv.Atoi(parts[0])
|
|
h, _ := strconv.Atoi(parts[1])
|
|
maxDim := w
|
|
if h > maxDim {
|
|
maxDim = h
|
|
}
|
|
if maxDim >= 3840 {
|
|
return "4k"
|
|
}
|
|
if maxDim >= 1920 {
|
|
return "1080p"
|
|
}
|
|
return "720p"
|
|
}
|
|
|
|
// SizeToVeoAspectRatio converts a "WxH" size string to a Veo aspect ratio.
|
|
func SizeToVeoAspectRatio(size string) string {
|
|
parts := strings.SplitN(strings.ToLower(size), "x", 2)
|
|
if len(parts) != 2 {
|
|
return "16:9"
|
|
}
|
|
w, _ := strconv.Atoi(parts[0])
|
|
h, _ := strconv.Atoi(parts[1])
|
|
if w <= 0 || h <= 0 {
|
|
return "16:9"
|
|
}
|
|
if h > w {
|
|
return "9:16"
|
|
}
|
|
return "16:9"
|
|
}
|
|
|
|
// VeoResolutionRatio returns the pricing multiplier for the given resolution.
|
|
// Standard resolutions (720p, 1080p) return 1.0.
|
|
// 4K returns a model-specific multiplier based on Google's official pricing.
|
|
func VeoResolutionRatio(modelName, resolution string) float64 {
|
|
if resolution != "4k" {
|
|
return 1.0
|
|
}
|
|
// 4K multipliers derived from Vertex AI official pricing (video+audio base):
|
|
// veo-3.1-generate: $0.60 / $0.40 = 1.5
|
|
// veo-3.1-fast-generate: $0.35 / $0.15 ≈ 2.333
|
|
// Veo 3.0 models do not support 4K; return 1.0 as fallback.
|
|
if strings.Contains(modelName, "3.1-fast-generate") {
|
|
return 2.333333
|
|
}
|
|
if strings.Contains(modelName, "3.1-generate") || strings.Contains(modelName, "3.1") {
|
|
return 1.5
|
|
}
|
|
return 1.0
|
|
}
|