generated from fahricansecer/boilerplate-be
@@ -268,37 +268,45 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
|
||||
const fallbackModel = 'gemini-3.1-flash-image-preview';
|
||||
|
||||
try {
|
||||
this.logger.debug(`🎨 Görsel üretiliyor: "${prompt.substring(0, 80)}..." [${aspectRatio}]`);
|
||||
this.logger.log(`🎨 Görsel üretiliyor: "${prompt.substring(0, 100)}..." [${aspectRatio}]`);
|
||||
|
||||
const enhancedPrompt = `Generate a high-quality image for this description: ${prompt}. Style: photorealistic, cinematic lighting, detailed. Aspect ratio: ${aspectRatio}. IMPORTANT: Generate only the image, no text response needed.`;
|
||||
// En-boy oranına göre yönlendirmeyi zorla
|
||||
const orientation = aspectRatio === '9:16' ? '(VERTICAL / PORTRAIT)' : aspectRatio === '16:9' ? '(HORIZONTAL / LANDSCAPE)' : '(SQUARE)';
|
||||
const enhancedPrompt = `Generate a high-quality, photorealistic image. Description: ${prompt}. Aspect ratio and framing: EXACTLY ${aspectRatio} ${orientation}. Style: cinematic lighting, detailed, professional. IMPORTANT: Return the generated image only, no text.`;
|
||||
|
||||
// ── Katman 1: gemini-2.5-flash-image (Nano Banana) ──
|
||||
try {
|
||||
this.logger.debug(`🔄 Katman 1: ${primaryModel} deneniyor...`);
|
||||
const result = await this.tryGenerateContentImage(primaryModel, enhancedPrompt);
|
||||
if (result) {
|
||||
this.logger.log(`✅ Görsel üretildi (${primaryModel}): ${(result.buffer.length / 1024).toFixed(1)} KB`);
|
||||
return result;
|
||||
// ── Katman 1: gemini-2.5-flash-image (Nano Banana) — 2 deneme ──
|
||||
for (let attempt = 1; attempt <= 2; attempt++) {
|
||||
try {
|
||||
this.logger.log(`🔄 Katman 1 (deneme ${attempt}/2): ${primaryModel}`);
|
||||
const result = await this.tryGenerateContentImage(primaryModel, enhancedPrompt);
|
||||
if (result) {
|
||||
this.logger.log(`✅ Görsel üretildi (${primaryModel}): ${(result.buffer.length / 1024).toFixed(1)} KB`);
|
||||
return result;
|
||||
}
|
||||
this.logger.warn(`⚠️ ${primaryModel} deneme ${attempt}: görsel döndürmedi (null response)`);
|
||||
if (attempt < 2) await this.sleep(2000);
|
||||
} catch (err1: any) {
|
||||
this.logger.warn(`⚠️ ${primaryModel} deneme ${attempt} hata: ${err1.message?.substring(0, 200)}`);
|
||||
if (attempt < 2) await this.sleep(2000);
|
||||
}
|
||||
} catch (err1: any) {
|
||||
this.logger.warn(`⚠️ ${primaryModel} başarısız: ${err1.message?.substring(0, 120)}`);
|
||||
}
|
||||
|
||||
// ── Katman 2: gemini-3.1-flash-image-preview (Nano Banana 2) ──
|
||||
try {
|
||||
this.logger.debug(`🔄 Katman 2: ${fallbackModel} deneniyor...`);
|
||||
this.logger.log(`🔄 Katman 2: ${fallbackModel}`);
|
||||
const result = await this.tryGenerateContentImage(fallbackModel, enhancedPrompt);
|
||||
if (result) {
|
||||
this.logger.log(`✅ Görsel üretildi (${fallbackModel}): ${(result.buffer.length / 1024).toFixed(1)} KB`);
|
||||
return result;
|
||||
}
|
||||
this.logger.warn(`⚠️ ${fallbackModel}: görsel döndürmedi (null response)`);
|
||||
} catch (err2: any) {
|
||||
this.logger.warn(`⚠️ ${fallbackModel} başarısız: ${err2.message?.substring(0, 120)}`);
|
||||
this.logger.warn(`⚠️ ${fallbackModel} hata: ${err2.message?.substring(0, 200)}`);
|
||||
}
|
||||
|
||||
// ── Katman 3: Imagen 4 Fast (generateImages API) ──
|
||||
try {
|
||||
this.logger.debug(`🔄 Katman 3: Imagen 4 Fast deneniyor...`);
|
||||
this.logger.log(`🔄 Katman 3: Imagen 4 Fast`);
|
||||
const response = await this.client!.models.generateImages({
|
||||
model: 'imagen-4.0-fast-generate-001',
|
||||
prompt: enhancedPrompt,
|
||||
@@ -306,7 +314,6 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
|
||||
numberOfImages: 1,
|
||||
aspectRatio: aspectRatio,
|
||||
outputMimeType: 'image/jpeg',
|
||||
personGeneration: 'ALLOW_ALL' as any,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -316,8 +323,9 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
|
||||
this.logger.log(`✅ Görsel üretildi (Imagen 4): ${(buffer.length / 1024).toFixed(1)} KB`);
|
||||
return { buffer, mimeType };
|
||||
}
|
||||
this.logger.warn('⚠️ Imagen 4: görsel döndürmedi');
|
||||
} catch (err3: any) {
|
||||
this.logger.warn(`⚠️ Imagen 4 başarısız: ${err3.message?.substring(0, 120)}`);
|
||||
this.logger.warn(`⚠️ Imagen 4 hata: ${err3.message?.substring(0, 200)}`);
|
||||
}
|
||||
|
||||
this.logger.error('❌ Tüm görsel üretim katmanları başarısız oldu');
|
||||
@@ -345,7 +353,15 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
|
||||
});
|
||||
|
||||
const candidate = response.candidates?.[0];
|
||||
const imagePart = candidate?.content?.parts?.find(
|
||||
|
||||
// Safety filter veya boş yanıt kontrolü
|
||||
if (!candidate?.content?.parts || candidate.content.parts.length === 0) {
|
||||
const finishReason = candidate?.finishReason || 'UNKNOWN';
|
||||
this.logger.warn(`⚠️ ${model}: boş yanıt (finishReason: ${finishReason})`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const imagePart = candidate.content.parts.find(
|
||||
(p: any) => p.inlineData?.mimeType?.startsWith('image/'),
|
||||
);
|
||||
|
||||
@@ -355,9 +371,20 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
|
||||
return { buffer, mimeType };
|
||||
}
|
||||
|
||||
// Text-only response geldi (görsel yok)
|
||||
const textParts = candidate.content.parts.filter((p: any) => p.text);
|
||||
if (textParts.length > 0) {
|
||||
this.logger.warn(`⚠️ ${model}: sadece text döndü, görsel yok. Text: "${textParts[0].text?.substring(0, 100)}"`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Basit uyku fonksiyonu — retry aralarında kullanılır */
|
||||
private sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sahne bazlı görsel üret — visualPrompt ve video stili kullanarak.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user