| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- package gemini
- import (
- "strconv"
- "strings"
- )
- // 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).
- 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 d
- }
- }
- }
- if stdDuration > 0 {
- return stdDuration
- }
- if s, err := strconv.Atoi(stdSeconds); err == nil && s > 0 {
- return s
- }
- 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
- }
|