Deploy: 2026-05-22 16:30:19

This commit is contained in:
Hamza-Ayed
2026-05-22 16:30:19 +03:00
parent 9a2666a1c8
commit 88c8a0987e
3 changed files with 101 additions and 10 deletions

View File

@@ -214,10 +214,68 @@ class GeminiService
}
/**
* Call Gemini API to generate a native audio (speech) response from text
* Call ElevenLabs API to generate a native audio response from text
*/
public static function generateAudioResponse(string $apiKey, string $systemPrompt, string $userMessage, string $voiceName = 'Puck'): ?array
public static function generateAudioResponseWithElevenLabs(string $elApiKey, string $text, string $voiceId): ?array
{
$url = 'https://api.elevenlabs.io/v1/text-to-speech/' . $voiceId;
$payload = json_encode([
'text' => $text,
'model_id' => 'eleven_multilingual_v2',
'voice_settings' => [
'stability' => 0.5,
'similarity_boost' => 0.8
]
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'xi-api-key: ' . $elApiKey
]);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
return [
'audio' => base64_encode($response),
'mimeType' => 'audio/mpeg'
];
} else {
error_log("[ElevenLabs API Error] HTTP " . $httpCode . " | Response: " . $response);
return null;
}
}
/**
* Call Gemini API or ElevenLabs to generate a native audio (speech) response from text
*/
public static function generateAudioResponse(
string $apiKey,
string $systemPrompt,
string $userMessage,
string $voiceName = 'Puck',
?string $elApiKey = null,
?string $elVoiceId = null
): ?array {
// Use ElevenLabs if the API Key is provided
if (!empty($elApiKey)) {
$voiceId = !empty($elVoiceId) ? $elVoiceId : 'pNInz6obpgDQGcFmaJgB'; // Default to Adam
$audioData = self::generateAudioResponseWithElevenLabs($elApiKey, $userMessage, $voiceId);
if ($audioData) {
return $audioData;
}
error_log("[TTS Service] ElevenLabs failed, falling back to Gemini TTS.");
}
// Gemini Fallback Logic:
$models = [
'gemini-3.1-flash-tts-preview',
'gemini-2.5-flash-preview-tts'
@@ -284,8 +342,15 @@ class GeminiService
/**
* Call Gemini API with audio inline data to generate a native audio response
*/
public static function generateAudioResponseFromAudio(string $apiKey, string $systemPrompt, string $audioBase64, string $mimeType, string $voiceName = 'Puck'): ?array
{
public static function generateAudioResponseFromAudio(
string $apiKey,
string $systemPrompt,
string $audioBase64,
string $mimeType,
string $voiceName = 'Puck',
?string $elApiKey = null,
?string $elVoiceId = null
): ?array {
// Step 1: Use gemini-flash-lite-latest (which supports audio input) to understand the audio message and generate a text reply
$replyText = self::generateResponseFromAudio($apiKey, $systemPrompt, $audioBase64, $mimeType);
if (empty($replyText)) {
@@ -293,7 +358,7 @@ class GeminiService
return null;
}
// Step 2: Use gemini-3.1-flash-tts-preview to convert the text response into a native audio voice note
return self::generateAudioResponse($apiKey, $systemPrompt, $replyText, $voiceName);
// Step 2: Use ElevenLabs or Gemini TTS to convert the text response into a native audio voice note
return self::generateAudioResponse($apiKey, $systemPrompt, $replyText, $voiceName, $elApiKey, $elVoiceId);
}
}