""" Google Cloud Voice Services Routes Replaces Azure voice services with Google Cloud Speech-to-Text and Translation """ import os import logging from fastapi import APIRouter, File, Form, UploadFile, Depends, HTTPException from typing import Optional from modules.connectors.connectorGoogleSpeech import ConnectorGoogleSpeech from modules.security.auth import getCurrentUser from modules.interfaces.interfaceAppModel import User logger = logging.getLogger(__name__) router = APIRouter(prefix="/voice-google", tags=["voice-google"]) # Global connector instance _google_speech_connector = None def get_google_speech_connector() -> ConnectorGoogleSpeech: """Get or create Google Cloud Speech connector instance.""" global _google_speech_connector if _google_speech_connector is None: try: # Get credentials path from environment or config credentials_path = os.getenv("GOOGLE_APPLICATION_CREDENTIALS") if not credentials_path: # Try to find credentials in common locations possible_paths = [ "credentials/google-service-account.json", "config/google-credentials.json", "google-credentials.json" ] for path in possible_paths: if os.path.exists(path): credentials_path = path break if not credentials_path: raise HTTPException( status_code=500, detail="Google Cloud credentials not found. Please set GOOGLE_APPLICATION_CREDENTIALS environment variable or place credentials file in project directory." ) _google_speech_connector = ConnectorGoogleSpeech(credentials_path) logger.info("✅ Google Cloud Speech connector initialized") except Exception as e: logger.error(f"❌ Failed to initialize Google Cloud Speech connector: {e}") raise HTTPException( status_code=500, detail=f"Failed to initialize Google Cloud Speech connector: {str(e)}" ) return _google_speech_connector @router.post("/speech-to-text") async def speech_to_text( audio_file: UploadFile = File(...), language: str = Form("de-DE"), current_user: User = Depends(getCurrentUser) ): """Convert speech to text using Google Cloud Speech-to-Text API.""" try: logger.info(f"🎤 Speech-to-text request: {audio_file.filename}, language: {language}") # Read audio file audio_content = await audio_file.read() logger.info(f"📊 Audio file size: {len(audio_content)} bytes") # Validate audio format connector = get_google_speech_connector() validation = connector.validate_audio_format(audio_content) if not validation["valid"]: raise HTTPException( status_code=400, detail=f"Invalid audio format: {validation.get('error', 'Unknown error')}" ) # Perform speech recognition result = await connector.speech_to_text( audio_content=audio_content, language=language ) if result["success"]: return { "success": True, "text": result["text"], "confidence": result["confidence"], "language": result["language"], "audio_info": { "size": len(audio_content), "format": validation["format"], "estimated_duration": validation.get("estimated_duration", 0) } } else: raise HTTPException( status_code=400, detail=f"Speech recognition failed: {result.get('error', 'Unknown error')}" ) except HTTPException: raise except Exception as e: logger.error(f"❌ Speech-to-text error: {e}") raise HTTPException( status_code=500, detail=f"Speech-to-text processing failed: {str(e)}" ) @router.post("/translate") async def translate_text( text: str = Form(...), source_language: str = Form("de"), target_language: str = Form("en"), current_user: User = Depends(getCurrentUser) ): """Translate text using Google Cloud Translation API.""" try: logger.info(f"🌐 Translation request: '{text}' ({source_language} -> {target_language})") if not text.strip(): raise HTTPException( status_code=400, detail="Empty text provided for translation" ) # Perform translation connector = get_google_speech_connector() result = await connector.translate_text( text=text, source_language=source_language, target_language=target_language ) if result["success"]: return { "success": True, "original_text": result["original_text"], "translated_text": result["translated_text"], "source_language": result["source_language"], "target_language": result["target_language"] } else: raise HTTPException( status_code=400, detail=f"Translation failed: {result.get('error', 'Unknown error')}" ) except HTTPException: raise except Exception as e: logger.error(f"❌ Translation error: {e}") raise HTTPException( status_code=500, detail=f"Translation processing failed: {str(e)}" ) @router.post("/realtime-interpreter") async def realtime_interpreter( audio_file: UploadFile = File(...), from_language: str = Form("de-DE"), to_language: str = Form("en-US"), connection_id: str = Form(None), current_user: User = Depends(getCurrentUser) ): """Real-time interpreter: speech to translated text using Google Cloud APIs.""" try: logger.info(f"🔄 Real-time interpreter request: {audio_file.filename}") logger.info(f" From: {from_language} -> To: {to_language}") # Read audio file audio_content = await audio_file.read() logger.info(f"📊 Audio file size: {len(audio_content)} bytes") # Save audio file for debugging debug_filename = f"debug_audio/audio_google_{audio_file.filename}" os.makedirs("debug_audio", exist_ok=True) with open(debug_filename, "wb") as f: f.write(audio_content) logger.info(f"💾 Saved audio file for debugging: {debug_filename}") # Validate audio format connector = get_google_speech_connector() validation = connector.validate_audio_format(audio_content) if not validation["valid"]: raise HTTPException( status_code=400, detail=f"Invalid audio format: {validation.get('error', 'Unknown error')}" ) # Perform complete pipeline: Speech-to-Text + Translation result = await connector.speech_to_translated_text( audio_content=audio_content, from_language=from_language, to_language=to_language ) if result["success"]: logger.info(f"✅ Real-time interpreter successful:") logger.info(f" Original: '{result['original_text']}'") logger.info(f" Translated: '{result['translated_text']}'") return { "success": True, "original_text": result["original_text"], "translated_text": result["translated_text"], "confidence": result["confidence"], "source_language": result["source_language"], "target_language": result["target_language"], "audio_info": { "size": len(audio_content), "format": validation["format"], "estimated_duration": validation.get("estimated_duration", 0) } } else: raise HTTPException( status_code=400, detail=f"Real-time interpreter failed: {result.get('error', 'Unknown error')}" ) except HTTPException: raise except Exception as e: logger.error(f"❌ Real-time interpreter error: {e}") raise HTTPException( status_code=500, detail=f"Real-time interpreter processing failed: {str(e)}" ) @router.get("/health") async def health_check(current_user: User = Depends(getCurrentUser)): """Health check for Google Cloud voice services.""" try: connector = get_google_speech_connector() # Test with a simple translation test_result = await connector.translate_text( text="Hello", source_language="en", target_language="de" ) if test_result["success"]: return { "status": "healthy", "service": "Google Cloud Speech-to-Text & Translation", "test_translation": test_result["translated_text"] } else: return { "status": "unhealthy", "error": test_result.get("error", "Unknown error") } except Exception as e: logger.error(f"❌ Health check failed: {e}") return { "status": "unhealthy", "error": str(e) }