Skip to main content
Glama
firebase
by firebase
main.go5.39 kB
// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "fmt" "io" "log" "net/http" "os" "strings" "time" "github.com/firebase/genkit/go/ai" "github.com/firebase/genkit/go/core" "github.com/firebase/genkit/go/genkit" "github.com/firebase/genkit/go/plugins/googlegenai" "google.golang.org/genai" ) func main() { ctx := context.Background() g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{})) operation, err := genkit.GenerateOperation(ctx, g, ai.WithMessages(ai.NewUserTextMessage("Cat racing mouse")), ai.WithModelName("googleai/veo-3.0-generate-001"), ai.WithConfig(&genai.GenerateVideosConfig{ NumberOfVideos: 1, AspectRatio: "16:9", DurationSeconds: genai.Ptr(int32(8)), Resolution: "720p", }), ) if err != nil { log.Fatalf("Failed to start video generation: %v", err) } log.Printf("Started operation: %s", operation.ID) printStatus(operation) operation, err = waitForCompletion(ctx, g, operation) if err != nil { log.Fatalf("Operation failed: %v", err) } log.Println("Video generation completed successfully!") if err := downloadGeneratedVideo(ctx, operation); err != nil { log.Fatalf("Failed to download video: %v", err) } log.Println("Video successfully downloaded to veo3_video.mp4") } // waitForCompletion polls the operation status until it completes. func waitForCompletion(ctx context.Context, g *genkit.Genkit, op *core.Operation[*ai.ModelResponse]) (*core.Operation[*ai.ModelResponse], error) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop() for !op.Done { select { case <-ctx.Done(): return nil, fmt.Errorf("context cancelled: %w", ctx.Err()) case <-ticker.C: updatedOp, err := genkit.CheckModelOperation(ctx, g, op) if err != nil { return nil, fmt.Errorf("failed to check status: %w", err) } if updatedOp.Error != nil { return nil, fmt.Errorf("operation error: %w", updatedOp.Error) } printStatus(updatedOp) op = updatedOp } } return op, nil } // printStatus prints the current status message from the operation. func printStatus(op *core.Operation[*ai.ModelResponse]) { if op.Output != nil && op.Output.Message != nil && len(op.Output.Message.Content) > 0 { log.Printf("Status: %s", op.Output.Message.Content[0].Text) } } // downloadGeneratedVideo downloads the generated video from the operation result. func downloadGeneratedVideo(ctx context.Context, operation *core.Operation[*ai.ModelResponse]) error { apiKey, err := getAPIKey() if err != nil { return err } videoURL, err := extractVideoURL(operation) if err != nil { return err } downloadURL := buildDownloadURL(videoURL, apiKey) return downloadVideo(ctx, downloadURL, "veo3_video.mp4") } // getAPIKey retrieves the API key from environment variables. func getAPIKey() (string, error) { apiKey := os.Getenv("GEMINI_API_KEY") if apiKey == "" { apiKey = os.Getenv("GOOGLE_API_KEY") } if apiKey == "" { return "", fmt.Errorf("no API key found. Please set GEMINI_API_KEY or GOOGLE_API_KEY environment variable") } return apiKey, nil } // extractVideoURL extracts the video URL from the operation output. func extractVideoURL(operation *core.Operation[*ai.ModelResponse]) (string, error) { if operation.Output == nil { return "", fmt.Errorf("operation output is nil") } if operation.Output.Message == nil { return "", fmt.Errorf("model response message is nil") } for _, part := range operation.Output.Message.Content { if part.IsMedia() && part.Text != "" { return part.Text, nil } } return "", fmt.Errorf("no video URL found in the operation output") } // buildDownloadURL appends the API key to the video URL if not already present. func buildDownloadURL(videoURL, apiKey string) string { if strings.Contains(videoURL, "key=") { return videoURL } separator := "?" if strings.Contains(videoURL, "?") { separator = "&" } return fmt.Sprintf("%s%skey=%s", videoURL, separator, apiKey) } // downloadVideo downloads a file from a URL and saves it to the specified filename. func downloadVideo(ctx context.Context, url, filename string) error { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return fmt.Errorf("failed to create HTTP request: %w", err) } client := &http.Client{} resp, err := client.Do(req) if err != nil { return fmt.Errorf("failed to download video: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("failed to download video: HTTP %d", resp.StatusCode) } file, err := os.Create(filename) if err != nil { return fmt.Errorf("failed to create output file: %w", err) } defer file.Close() if _, err := io.Copy(file, resp.Body); err != nil { return fmt.Errorf("failed to write video data to file: %w", err) } return nil }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/firebase/genkit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server