Files
new-api-hunter/relay/channel/task/gemini/image.go
CaIon 32d9ae1f83 feat(gemini): implement video generation configuration and billing estimation
- Added Gemini video generation configuration structures and payloads.
- Introduced functions for parsing and resolving video duration and resolution from metadata.
- Enhanced the Vertex adaptor to support Gemini video generation requests and billing estimation based on duration and resolution.
- Updated model pricing settings for new Gemini video models.
2026-02-28 17:37:08 +08:00

101 lines
2.3 KiB
Go

package gemini
import (
"encoding/base64"
"io"
"net/http"
"strings"
"github.com/QuantumNous/new-api/constant"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/gin-gonic/gin"
)
const maxVeoImageSize = 20 * 1024 * 1024 // 20 MB
// ExtractMultipartImage reads the first `input_reference` file from a multipart
// form upload and returns a VeoImageInput. Returns nil if no file is present.
func ExtractMultipartImage(c *gin.Context, info *relaycommon.RelayInfo) *VeoImageInput {
mf, err := c.MultipartForm()
if err != nil {
return nil
}
files, exists := mf.File["input_reference"]
if !exists || len(files) == 0 {
return nil
}
fh := files[0]
if fh.Size > maxVeoImageSize {
return nil
}
file, err := fh.Open()
if err != nil {
return nil
}
defer file.Close()
fileBytes, err := io.ReadAll(file)
if err != nil {
return nil
}
mimeType := fh.Header.Get("Content-Type")
if mimeType == "" || mimeType == "application/octet-stream" {
mimeType = http.DetectContentType(fileBytes)
}
info.Action = constant.TaskActionGenerate
return &VeoImageInput{
BytesBase64Encoded: base64.StdEncoding.EncodeToString(fileBytes),
MimeType: mimeType,
}
}
// ParseImageInput parses an image string (data URI or raw base64) into a
// VeoImageInput. Returns nil if the input is empty or invalid.
// TODO: support downloading HTTP URL images and converting to base64
func ParseImageInput(imageStr string) *VeoImageInput {
imageStr = strings.TrimSpace(imageStr)
if imageStr == "" {
return nil
}
if strings.HasPrefix(imageStr, "data:") {
return parseDataURI(imageStr)
}
raw, err := base64.StdEncoding.DecodeString(imageStr)
if err != nil {
return nil
}
return &VeoImageInput{
BytesBase64Encoded: imageStr,
MimeType: http.DetectContentType(raw),
}
}
func parseDataURI(uri string) *VeoImageInput {
// data:image/png;base64,iVBOR...
rest := uri[len("data:"):]
idx := strings.Index(rest, ",")
if idx < 0 {
return nil
}
meta := rest[:idx]
b64 := rest[idx+1:]
if b64 == "" {
return nil
}
mimeType := "application/octet-stream"
parts := strings.SplitN(meta, ";", 2)
if len(parts) >= 1 && parts[0] != "" {
mimeType = parts[0]
}
return &VeoImageInput{
BytesBase64Encoded: b64,
MimeType: mimeType,
}
}