ciyidogan commited on
Commit
bea4a17
Β·
verified Β·
1 Parent(s): 39a9195

Create audio_routes.py

Browse files
Files changed (1) hide show
  1. audio_routes.py +167 -0
audio_routes.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ """Audio API endpoints for Flare
3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
+ Provides text-to-speech (TTS) and speech-to-text (STT) endpoints.
5
+ """
6
+
7
+ from fastapi import APIRouter, HTTPException, Response, Body
8
+ from pydantic import BaseModel
9
+ from typing import Optional
10
+ from datetime import datetime
11
+ import sys
12
+
13
+ from logger import log_info, log_error, log_warning, log_debug
14
+ from tts_factory import TTSFactory
15
+ from tts_preprocessor import TTSPreprocessor
16
+ from config_provider import ConfigProvider
17
+
18
+ router = APIRouter(tags=["audio"])
19
+
20
+ # ===================== Models =====================
21
+ class TTSRequest(BaseModel):
22
+ text: str
23
+ voice_id: Optional[str] = None
24
+ language: Optional[str] = "tr-TR"
25
+
26
+ class STTRequest(BaseModel):
27
+ audio_data: str # Base64 encoded audio
28
+ language: Optional[str] = "tr-TR"
29
+ format: Optional[str] = "webm" # webm, wav, mp3
30
+
31
+ # ===================== Helpers =====================
32
+ def log(message: str):
33
+ """Log helper with timestamp"""
34
+ timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
35
+ print(f"[{timestamp}] {message}")
36
+ sys.stdout.flush()
37
+
38
+ # ===================== TTS Endpoints =====================
39
+ @router.post("/tts/generate")
40
+ async def generate_tts(request: TTSRequest):
41
+ """Generate TTS audio from text - public endpoint for chat"""
42
+ try:
43
+ # Create TTS provider
44
+ tts_provider = TTSFactory.create_provider()
45
+
46
+ if not tts_provider:
47
+ # Return empty response for no TTS
48
+ log_info("πŸ“΅ TTS disabled - returning empty response")
49
+ return Response(
50
+ content=b"",
51
+ media_type="audio/mpeg",
52
+ headers={"X-TTS-Status": "disabled"}
53
+ )
54
+
55
+ log_info(f"🎀 TTS request: '{request.text[:50]}...' with provider: {tts_provider.get_provider_name()}")
56
+
57
+ # Preprocess text if needed
58
+ preprocessor = TTSPreprocessor(language=request.language)
59
+ processed_text = preprocessor.preprocess(
60
+ request.text,
61
+ tts_provider.get_preprocessing_flags()
62
+ )
63
+
64
+ log_debug(f"πŸ“ Preprocessed text: {processed_text[:100]}...")
65
+
66
+ # Generate audio
67
+ audio_data = await tts_provider.synthesize(
68
+ text=processed_text,
69
+ voice_id=request.voice_id
70
+ )
71
+
72
+ log_info(f"βœ… TTS generated {len(audio_data)} bytes of audio")
73
+
74
+ # Return audio as binary response
75
+ return Response(
76
+ content=audio_data,
77
+ media_type="audio/mpeg",
78
+ headers={
79
+ "Content-Disposition": 'inline; filename="tts_output.mp3"',
80
+ "X-TTS-Provider": tts_provider.get_provider_name(),
81
+ "X-TTS-Language": request.language,
82
+ "Cache-Control": "no-cache"
83
+ }
84
+ )
85
+
86
+ except Exception as e:
87
+ log_error("❌ TTS generation error", e)
88
+ raise HTTPException(
89
+ status_code=500,
90
+ detail=f"TTS generation failed: {str(e)}"
91
+ )
92
+
93
+ @router.get("/tts/voices")
94
+ async def get_tts_voices():
95
+ """Get available TTS voices - public endpoint"""
96
+ try:
97
+ tts_provider = TTSFactory.create_provider()
98
+
99
+ if not tts_provider:
100
+ return {
101
+ "voices": [],
102
+ "provider": "none",
103
+ "enabled": False
104
+ }
105
+
106
+ voices = tts_provider.get_supported_voices()
107
+
108
+ # Convert dict to list format
109
+ voice_list = [
110
+ {"id": voice_id, "name": voice_name}
111
+ for voice_id, voice_name in voices.items()
112
+ ]
113
+
114
+ return {
115
+ "voices": voice_list,
116
+ "provider": tts_provider.get_provider_name(),
117
+ "enabled": True
118
+ }
119
+
120
+ except Exception as e:
121
+ log_error("❌ Error getting TTS voices", e)
122
+ return {
123
+ "voices": [],
124
+ "provider": "error",
125
+ "enabled": False,
126
+ "error": str(e)
127
+ }
128
+
129
+ @router.get("/tts/status")
130
+ async def get_tts_status():
131
+ """Get TTS service status"""
132
+ cfg = ConfigProvider.get()
133
+
134
+ return {
135
+ "enabled": cfg.global_config.tts_provider.name != "no_tts",
136
+ "provider": cfg.global_config.tts_provider.name,
137
+ "provider_config": {
138
+ "name": cfg.global_config.tts_provider.name,
139
+ "has_api_key": bool(cfg.global_config.tts_provider.api_key),
140
+ "endpoint": cfg.global_config.tts_provider.endpoint
141
+ }
142
+ }
143
+
144
+ # ===================== STT Endpoints (Future) =====================
145
+ @router.post("/stt/transcribe")
146
+ async def transcribe_audio(request: STTRequest):
147
+ """Transcribe audio to text - to be implemented"""
148
+ # TODO: Implement when STT factory is ready
149
+ raise HTTPException(
150
+ status_code=501,
151
+ detail="STT transcription not yet implemented"
152
+ )
153
+
154
+ @router.get("/stt/status")
155
+ async def get_stt_status():
156
+ """Get STT service status"""
157
+ cfg = ConfigProvider.get()
158
+
159
+ return {
160
+ "enabled": cfg.global_config.stt_provider.name != "no_stt",
161
+ "provider": cfg.global_config.stt_provider.name,
162
+ "provider_config": {
163
+ "name": cfg.global_config.stt_provider.name,
164
+ "has_api_key": bool(cfg.global_config.stt_provider.api_key),
165
+ "endpoint": cfg.global_config.stt_provider.endpoint
166
+ }
167
+ }