main
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled

This commit is contained in:
Harun CAN
2026-03-30 00:21:32 +03:00
parent 85c35c73e8
commit acb103657b
29 changed files with 11473 additions and 13081 deletions
+96
View File
@@ -237,4 +237,100 @@ IMPORTANT: Only output valid JSON, no markdown code blocks or other text.`;
throw new Error('Failed to parse AI response as JSON');
}
}
// ── Görsel Üretim (Gemini Image Generation) ─────────────────────────
/**
* Gemini Image Generation API ile görsel üret.
* Raspberry Pi 5 bellek koruması için buffer olarak döner.
*
* @param prompt - İngilizce görsel açıklaması
* @param aspectRatio - Görsel en-boy oranı (16:9, 9:16, 1:1)
* @returns Base64 decoded image buffer ve mime type
*/
async generateImage(
prompt: string,
aspectRatio: '16:9' | '9:16' | '1:1' = '16:9',
): Promise<{ buffer: Buffer; mimeType: string } | null> {
if (!this.isAvailable()) {
throw new Error('Gemini AI is not available. Check your configuration.');
}
const imageModel = this.configService.get<string>(
'gemini.imageModel',
'gemini-2.0-flash-preview-image-generation',
);
try {
this.logger.debug(`🎨 Görsel üretiliyor: "${prompt.substring(0, 80)}..." [${aspectRatio}]`);
const response = await this.client!.models.generateContent({
model: imageModel,
contents: [
{
role: 'user',
parts: [
{
text: `Generate a high-quality image for this description: ${prompt}. Aspect ratio: ${aspectRatio}. Style: photorealistic, cinematic lighting, detailed.`,
},
],
},
],
config: {
responseModalities: ['TEXT', 'IMAGE'] as any,
},
});
// Gemini image response'dan image part'ı çıkar
const parts = (response as any).candidates?.[0]?.content?.parts || [];
for (const part of parts) {
if (part.inlineData?.data) {
const buffer = Buffer.from(part.inlineData.data, 'base64');
const mimeType = part.inlineData.mimeType || 'image/png';
this.logger.log(`✅ Görsel üretildi: ${(buffer.length / 1024).toFixed(1)} KB`);
return { buffer, mimeType };
}
}
this.logger.warn('Gemini görsel üretemedi — boş yanıt');
return null;
} catch (error) {
this.logger.error(`Gemini görsel üretim hatası: ${error}`);
throw error;
}
}
/**
* Sahne bazlı görsel üret — visualPrompt ve video stili kullanarak.
*
* @param visualPrompt - Sahnenin İngilizce görsel açıklaması
* @param style - Video stili (cinematic, documentary, educational vb.)
* @param aspectRatio - En-boy oranı
* @returns Buffer ve mimeType
*/
async generateImageForScene(
visualPrompt: string,
style: string = 'cinematic',
aspectRatio: '16:9' | '9:16' | '1:1' = '16:9',
): Promise<{ buffer: Buffer; mimeType: string } | null> {
const enhancedPrompt = `${visualPrompt}. Style: ${style}, professional production quality, volumetric lighting, sharp details, 8K resolution.`;
return this.generateImage(enhancedPrompt, aspectRatio);
}
/**
* Video için thumbnail görsel üret — proje başlığı ve açıklamasından.
*
* @param title - Video başlığı
* @param description - Video açıklaması
* @returns Buffer ve mimeType
*/
async generateThumbnail(
title: string,
description: string,
): Promise<{ buffer: Buffer; mimeType: string } | null> {
const prompt = `Create a compelling YouTube video thumbnail for a video titled "${title}". ${description}. Make it eye-catching with bold, dynamic composition. No text overlay needed.`;
return this.generateImage(prompt, '16:9');
}
}