Update app.py
Browse files
app.py
CHANGED
@@ -51,9 +51,14 @@ if SF_ENABLED:
|
|
51 |
ENCRYPTION_KEY = os.getenv("ENCRYPTION_KEY") or Fernet.generate_key()
|
52 |
fernet = Fernet(ENCRYPTION_KEY)
|
53 |
|
54 |
-
# Initialize text-to-speech
|
55 |
-
tts_engine =
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
# Initialize local models
|
59 |
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
|
@@ -300,6 +305,9 @@ def generate_report():
|
|
300 |
|
301 |
async def speak_response(text):
|
302 |
"""Convert text to speech."""
|
|
|
|
|
|
|
303 |
try:
|
304 |
def sync_speak():
|
305 |
tts_engine.say(text)
|
@@ -388,6 +396,55 @@ async def analyze_voice(audio_file, language="en", user_id="anonymous", consent_
|
|
388 |
logger.error(f"Voice analysis failed: {str(e)}")
|
389 |
return f"Error: {str(e)}"
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
async def voicebot_interface(audio_file, language="en", user_id="anonymous", consent_granted=True):
|
392 |
"""Gradio interface wrapper."""
|
393 |
return await analyze_voice(audio_file, language, user_id, consent_granted)
|
|
|
51 |
ENCRYPTION_KEY = os.getenv("ENCRYPTION_KEY") or Fernet.generate_key()
|
52 |
fernet = Fernet(ENCRYPTION_KEY)
|
53 |
|
54 |
+
# Initialize text-to-speech with fallback
|
55 |
+
tts_engine = None
|
56 |
+
try:
|
57 |
+
tts_engine = pyttsx3.init()
|
58 |
+
tts_engine.setProperty("rate", 150)
|
59 |
+
logger.info("pyttsx3 initialized successfully")
|
60 |
+
except Exception as e:
|
61 |
+
logger.warning(f"Failed to initialize pyttsx3: {str(e)}. Text-to-speech disabled.")
|
62 |
|
63 |
# Initialize local models
|
64 |
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
|
|
|
305 |
|
306 |
async def speak_response(text):
|
307 |
"""Convert text to speech."""
|
308 |
+
if not tts_engine:
|
309 |
+
logger.warning("Text-to-speech unavailable; skipping")
|
310 |
+
return
|
311 |
try:
|
312 |
def sync_speak():
|
313 |
tts_engine.say(text)
|
|
|
396 |
logger.error(f"Voice analysis failed: {str(e)}")
|
397 |
return f"Error: {str(e)}"
|
398 |
|
399 |
+
async def test_with_sample_audio(language="en", user_id="anonymous", consent_granted=True):
|
400 |
+
"""Test with synthetic audio."""
|
401 |
+
temp_dir = os.path.join(tempfile.gettempdir(), "audio_samples")
|
402 |
+
if not ensure_writable_dir(temp_dir):
|
403 |
+
fallback_dir = os.path.join(os.getcwd(), "temp_audio_samples")
|
404 |
+
if not ensure_writable_dir(fallback_dir):
|
405 |
+
logger.error(f"Temp directories {temp_dir} and {fallback_dir} not writable")
|
406 |
+
return f"Error: Temp directories not writable"
|
407 |
+
temp_dir = fallback_dir
|
408 |
+
|
409 |
+
sample_audio_path = os.path.join(temp_dir, "dummy_test.wav")
|
410 |
+
logger.info(f"Generating synthetic audio at: {sample_audio_path}")
|
411 |
+
sr = 16000
|
412 |
+
t = np.linspace(0, 2, 2 * sr)
|
413 |
+
freq_mod = 440 + 10 * np.sin(2 * np.pi * 0.5 * t)
|
414 |
+
amplitude_mod = 0.5 + 0.1 * np.sin(2 * np.pi * 0.3 * t)
|
415 |
+
noise = 0.01 * np.random.normal(0, 1, len(t))
|
416 |
+
dummy_audio = amplitude_mod * np.sin(2 * np.pi * freq_mod * t) + noise
|
417 |
+
try:
|
418 |
+
soundfile.write(dummy_audio, sr, sample_audio_path)
|
419 |
+
logger.info(f"Generated synthetic audio: {sample_audio_path}")
|
420 |
+
except Exception as e:
|
421 |
+
logger.error(f"Failed to write synthetic audio: {str(e)}")
|
422 |
+
return f"Error: Failed to generate synthetic audio: {str(e)}"
|
423 |
+
|
424 |
+
if not os.path.exists(sample_audio_path):
|
425 |
+
logger.error(f"Synthetic audio not created: {sample_audio_path}")
|
426 |
+
return f"Error: Synthetic audio not created: {sample_audio_path}"
|
427 |
+
|
428 |
+
mock_transcription = "I have a cough and sore throat"
|
429 |
+
logger.info(f"Mock transcription: {mock_transcription}")
|
430 |
+
prediction, score = analyze_symptoms(mock_transcription)
|
431 |
+
feedback = (
|
432 |
+
"No health condition detected, consult a doctor if symptoms persist. This is not a medical diagnosis."
|
433 |
+
if prediction == "No health condition detected"
|
434 |
+
else f"Possible {prediction.lower()} detected, consult a doctor. This is not a medical diagnosis."
|
435 |
+
)
|
436 |
+
logger.info(f"Test feedback: {feedback}, Prediction: {prediction}, Score: {score:.4f}")
|
437 |
+
|
438 |
+
# Save to Salesforce
|
439 |
+
save_to_salesforce(user_id, mock_transcription, prediction, score, feedback, consent_granted)
|
440 |
+
|
441 |
+
try:
|
442 |
+
os.remove(sample_audio_path)
|
443 |
+
logger.debug(f"Deleted test audio: {sample_audio_path}")
|
444 |
+
except Exception:
|
445 |
+
pass
|
446 |
+
return feedback
|
447 |
+
|
448 |
async def voicebot_interface(audio_file, language="en", user_id="anonymous", consent_granted=True):
|
449 |
"""Gradio interface wrapper."""
|
450 |
return await analyze_voice(audio_file, language, user_id, consent_granted)
|