persona-community-2/pkg/mediagen/adapters/gemini.go
jordan cb3d4d5786
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/manual/woodpecker Pipeline was successful
Initialize project from skeleton template
2026-02-23 10:53:55 +00:00

160 lines
4.2 KiB
Go

// Package adapters provides mediagen provider adapters for various AI services.
package adapters
import (
"context"
"fmt"
"git.threesix.ai/jordan/persona-community-2/pkg/gemini"
"git.threesix.ai/jordan/persona-community-2/pkg/mediagen"
)
// GeminiProvider adapts pkg/gemini to the mediagen interfaces.
type GeminiProvider struct {
client *gemini.Client
}
// NewGeminiProvider creates a new Gemini provider adapter.
func NewGeminiProvider(client *gemini.Client) *GeminiProvider {
return &GeminiProvider{client: client}
}
// Name implements mediagen.ImageGenerator and mediagen.VideoGenerator.
func (p *GeminiProvider) Name() string {
return "gemini"
}
// Health implements mediagen.ImageGenerator and mediagen.VideoGenerator.
func (p *GeminiProvider) Health(ctx context.Context) error {
if err := p.client.Health(ctx); err != nil {
return mediagen.NewProviderError("gemini", "Health", err)
}
return nil
}
// validImageMIMETypes lists MIME types supported for reference images
var geminiValidImageMIMETypes = map[string]bool{
"image/png": true,
"image/jpeg": true,
"image/webp": true,
}
// GenerateImage implements mediagen.ImageGenerator.
// Note: Gemini's native image generation currently supports only 1 image per request.
// The Count field is ignored.
func (p *GeminiProvider) GenerateImage(ctx context.Context, req mediagen.ImageRequest) (*mediagen.ImageResponse, error) {
// Validate reference image MIME type if provided
if len(req.ReferenceImage) > 0 && req.ReferenceMime != "" {
if !geminiValidImageMIMETypes[req.ReferenceMime] {
return nil, fmt.Errorf("unsupported reference image MIME type: %s (supported: image/png, image/jpeg, image/webp)", req.ReferenceMime)
}
}
// Map unified request to Gemini-specific request
gemReq := gemini.ImageRequest{
Prompt: req.Prompt,
Model: req.Model,
Size: req.Size,
AspectRatio: req.AspectRatio,
ReferenceImage: req.ReferenceImage,
ReferenceMime: req.ReferenceMime,
Seed: req.Seed,
}
// Call Gemini client
gemResp, err := p.client.GenerateImage(ctx, gemReq)
if err != nil {
return nil, mediagen.NewProviderError("gemini", "GenerateImage", err)
}
// Convert response to unified format
images := make([]mediagen.Image, 0, len(gemResp.Images))
for _, img := range gemResp.Images {
images = append(images, mediagen.Image{
Data: img.Data,
MimeType: img.MimeType,
})
}
return &mediagen.ImageResponse{
Images: images,
Seed: gemResp.Seed,
}, nil
}
// GenerateVideo implements mediagen.VideoGenerator.
func (p *GeminiProvider) GenerateVideo(ctx context.Context, req mediagen.VideoRequest) (*mediagen.VideoResponse, error) {
// Map unified request to Gemini-specific request
gemReq := gemini.VideoRequest{
Prompt: req.Prompt,
Model: req.Model,
AspectRatio: req.AspectRatio,
Duration: req.Duration,
}
// Convert first reference image if provided
if len(req.ReferenceImages) > 0 {
img := req.ReferenceImages[0]
gemReq.Image = img.Data
gemReq.ImageMimeType = img.MimeType
}
// Call Gemini client
gemResp, err := p.client.GenerateVideo(ctx, gemReq)
if err != nil {
return nil, mediagen.NewProviderError("gemini", "GenerateVideo", err)
}
// If video was returned as URI, download it
var videoData []byte
var mimeType string
var url string
if len(gemResp.Video.Data) > 0 {
videoData = gemResp.Video.Data
mimeType = gemResp.Video.MimeType
}
if gemResp.Video.URI != "" {
url = gemResp.Video.URI
// If we don't have data yet, download from URI
if len(videoData) == 0 {
downloaded, downloadErr := downloadVideo(ctx, gemResp.Video.URI)
if downloadErr != nil {
// Return URI-only response if download fails (caller can retry download)
return &mediagen.VideoResponse{
Videos: []mediagen.Video{
{
URL: url,
MimeType: "video/mp4",
},
},
}, nil
}
videoData = downloaded
mimeType = "video/mp4"
}
}
if mimeType == "" {
mimeType = "video/mp4"
}
return &mediagen.VideoResponse{
Videos: []mediagen.Video{
{
Data: videoData,
MimeType: mimeType,
URL: url,
},
},
}, nil
}
// Compile-time interface check
var (
_ mediagen.ImageGenerator = (*GeminiProvider)(nil)
_ mediagen.VideoGenerator = (*GeminiProvider)(nil)
)