feat: add Imagen 3 as primary image generator
- Try Imagen 3 first (best quality, $0.03/image) - Fall back to Gemini via RunPod if Imagen fails - Uses 3:4 aspect ratio for portrait zine pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a5f067e5a6
commit
fd6f16f299
|
|
@ -109,26 +109,79 @@ async function generateImageWithGemini(
|
||||||
throw new Error("GEMINI_API_KEY not configured");
|
throw new Error("GEMINI_API_KEY not configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runpodApiKey) {
|
// Try Imagen 3 first (best quality, may work directly)
|
||||||
throw new Error("RUNPOD_API_KEY not configured - required for Gemini proxy");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use RunPod US proxy to bypass geo-restrictions on Gemini image generation
|
|
||||||
try {
|
try {
|
||||||
const result = await generateWithRunPodGeminiProxy(prompt, apiKey, runpodApiKey, runpodEndpointId);
|
const result = await generateWithImagen3(prompt, apiKey);
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log("✅ Generated image with Gemini 2.0 Flash via RunPod proxy");
|
console.log("✅ Generated image with Imagen 3");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("RunPod Gemini proxy error:", error);
|
console.error("Imagen 3 error:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: Create styled placeholder with actual content
|
// Fallback to Gemini via RunPod proxy
|
||||||
|
if (runpodApiKey) {
|
||||||
|
try {
|
||||||
|
const result = await generateWithRunPodGeminiProxy(prompt, apiKey, runpodApiKey, runpodEndpointId);
|
||||||
|
if (result) {
|
||||||
|
console.log("✅ Generated image with Gemini via RunPod proxy");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("RunPod Gemini proxy error:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final fallback: Create styled placeholder
|
||||||
console.log("Using styled placeholder image for page", outline.pageNumber);
|
console.log("Using styled placeholder image for page", outline.pageNumber);
|
||||||
return createStyledPlaceholder(outline, style);
|
return createStyledPlaceholder(outline, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Imagen 3 - Google's best image generation model
|
||||||
|
async function generateWithImagen3(prompt: string, apiKey: string): Promise<string | null> {
|
||||||
|
const imagenUrl = `https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-002:predict?key=${apiKey}`;
|
||||||
|
|
||||||
|
console.log("Calling Imagen 3 API...");
|
||||||
|
|
||||||
|
const response = await fetch(imagenUrl, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
instances: [{ prompt: prompt }],
|
||||||
|
parameters: {
|
||||||
|
sampleCount: 1,
|
||||||
|
aspectRatio: "3:4", // Portrait for zine pages
|
||||||
|
safetyFilterLevel: "BLOCK_ONLY_HIGH",
|
||||||
|
personGeneration: "ALLOW_ALL",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
console.error("Imagen 3 API error:", response.status, errorText);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.error) {
|
||||||
|
console.error("Imagen 3 error:", JSON.stringify(data.error));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract image from predictions
|
||||||
|
const predictions = data.predictions || [];
|
||||||
|
if (predictions.length > 0 && predictions[0].bytesBase64Encoded) {
|
||||||
|
console.log("✅ Successfully received image from Imagen 3");
|
||||||
|
return predictions[0].bytesBase64Encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error("No image in Imagen 3 response");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Gemini image generation via RunPod US proxy (bypasses geo-restrictions)
|
// Gemini image generation via RunPod US proxy (bypasses geo-restrictions)
|
||||||
// Uses gemini-2.0-flash-exp-image-generation for best quality with text rendering
|
// Uses gemini-2.0-flash-exp-image-generation for best quality with text rendering
|
||||||
async function generateWithRunPodGeminiProxy(
|
async function generateWithRunPodGeminiProxy(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue