Spaces:
Sleeping
Sleeping
Commit ·
4c17c6a
1
Parent(s): 899843c
Add 8999999999999
Browse files- voice_service.py +41 -6
voice_service.py
CHANGED
|
@@ -40,8 +40,10 @@ class VoiceService:
|
|
| 40 |
import edge_tts
|
| 41 |
self.tts_available = True
|
| 42 |
logger.info("✅ Edge TTS initialized")
|
|
|
|
|
|
|
|
|
|
| 43 |
elif self.tts_provider == "openai-tts":
|
| 44 |
-
# OpenAI TTS would require OpenAI API key
|
| 45 |
self.tts_available = False
|
| 46 |
logger.info("⚠️ OpenAI TTS not configured")
|
| 47 |
else:
|
|
@@ -158,22 +160,55 @@ class VoiceService:
|
|
| 158 |
try:
|
| 159 |
if self.tts_provider == "edge-tts":
|
| 160 |
import edge_tts
|
| 161 |
-
|
| 162 |
# Create TTS communication
|
| 163 |
communicate = edge_tts.Communicate(text, voice, rate=f"{int((self.voice_speed - 1) * 100):+d}%")
|
| 164 |
-
|
| 165 |
-
# Generate audio
|
| 166 |
audio_data = b""
|
| 167 |
async for chunk in communicate.stream():
|
| 168 |
if chunk["type"] == "audio":
|
| 169 |
audio_data += chunk["data"]
|
| 170 |
-
|
| 171 |
return audio_data
|
| 172 |
-
|
|
|
|
|
|
|
| 173 |
except Exception as e:
|
| 174 |
logger.error(f"❌ TTS Error: {e}")
|
| 175 |
return None
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
async def speech_to_text(self, audio_file_path: str, user_language: str = None) -> Optional[str]:
|
| 178 |
"""
|
| 179 |
Convert speech audio to text
|
|
|
|
| 40 |
import edge_tts
|
| 41 |
self.tts_available = True
|
| 42 |
logger.info("✅ Edge TTS initialized")
|
| 43 |
+
elif self.tts_provider == "murf":
|
| 44 |
+
self.tts_available = True
|
| 45 |
+
logger.info("✅ Murf AI TTS initialized")
|
| 46 |
elif self.tts_provider == "openai-tts":
|
|
|
|
| 47 |
self.tts_available = False
|
| 48 |
logger.info("⚠️ OpenAI TTS not configured")
|
| 49 |
else:
|
|
|
|
| 160 |
try:
|
| 161 |
if self.tts_provider == "edge-tts":
|
| 162 |
import edge_tts
|
|
|
|
| 163 |
# Create TTS communication
|
| 164 |
communicate = edge_tts.Communicate(text, voice, rate=f"{int((self.voice_speed - 1) * 100):+d}%")
|
|
|
|
|
|
|
| 165 |
audio_data = b""
|
| 166 |
async for chunk in communicate.stream():
|
| 167 |
if chunk["type"] == "audio":
|
| 168 |
audio_data += chunk["data"]
|
|
|
|
| 169 |
return audio_data
|
| 170 |
+
elif self.tts_provider == "murf":
|
| 171 |
+
audio_data = await self._murf_tts(text, voice)
|
| 172 |
+
return audio_data
|
| 173 |
except Exception as e:
|
| 174 |
logger.error(f"❌ TTS Error: {e}")
|
| 175 |
return None
|
| 176 |
|
| 177 |
+
async def _murf_tts(self, text: str, voice: str = None) -> Optional[bytes]:
|
| 178 |
+
"""
|
| 179 |
+
Call Murf AI TTS API to convert text to speech
|
| 180 |
+
Returns audio bytes or None
|
| 181 |
+
"""
|
| 182 |
+
import aiohttp
|
| 183 |
+
import os
|
| 184 |
+
murf_api_key = os.environ.get("MURF_API_KEY", "ap2_947765d6-b958-4493-a681-d05f89a63276")
|
| 185 |
+
murf_url = "https://api.murf.ai/v1/speech/generate"
|
| 186 |
+
payload = {
|
| 187 |
+
"text": text,
|
| 188 |
+
"voice": voice or "en-US-1", # Default Murf voice
|
| 189 |
+
"format": "mp3"
|
| 190 |
+
}
|
| 191 |
+
headers = {
|
| 192 |
+
"Authorization": f"Bearer {murf_api_key}",
|
| 193 |
+
"Content-Type": "application/json"
|
| 194 |
+
}
|
| 195 |
+
try:
|
| 196 |
+
async with aiohttp.ClientSession() as session:
|
| 197 |
+
async with session.post(murf_url, json=payload, headers=headers) as resp:
|
| 198 |
+
if resp.status == 200:
|
| 199 |
+
result = await resp.json()
|
| 200 |
+
audio_url = result.get("audio_url")
|
| 201 |
+
if audio_url:
|
| 202 |
+
async with session.get(audio_url) as audio_resp:
|
| 203 |
+
if audio_resp.status == 200:
|
| 204 |
+
return await audio_resp.read()
|
| 205 |
+
logger.error(f"❌ Murf TTS: No audio_url in response: {result}")
|
| 206 |
+
else:
|
| 207 |
+
logger.error(f"❌ Murf TTS API error: {resp.status} {await resp.text()}")
|
| 208 |
+
except Exception as e:
|
| 209 |
+
logger.error(f"❌ Murf TTS Exception: {e}")
|
| 210 |
+
return None
|
| 211 |
+
|
| 212 |
async def speech_to_text(self, audio_file_path: str, user_language: str = None) -> Optional[str]:
|
| 213 |
"""
|
| 214 |
Convert speech audio to text
|