Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -61,15 +61,21 @@ def extract_health_features(audio, sr):
|
|
| 61 |
raise ValueError("No voiced segments detected")
|
| 62 |
voiced_audio = np.concatenate(voiced_frames)
|
| 63 |
|
| 64 |
-
# Pitch (F0)
|
| 65 |
-
pitches, magnitudes = librosa.piptrack(y=voiced_audio, sr=sr, fmin=
|
| 66 |
-
valid_pitches = [p for p in pitches[magnitudes > 0] if p
|
| 67 |
pitch = np.mean(valid_pitches) if valid_pitches else 0
|
| 68 |
jitter = np.std(valid_pitches) / pitch if pitch and valid_pitches else 0
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
# Shimmer (amplitude variation)
|
| 71 |
amplitudes = librosa.feature.rms(y=voiced_audio, frame_length=2048, hop_length=512)[0]
|
| 72 |
shimmer = np.std(amplitudes) / np.mean(amplitudes) if np.mean(amplitudes) else 0
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
# Energy
|
| 75 |
energy = np.mean(librosa.feature.rms(y=voiced_audio, frame_length=2048, hop_length=512)[0])
|
|
@@ -102,11 +108,11 @@ def analyze_symptoms(text):
|
|
| 102 |
text = text.lower()
|
| 103 |
feedback = []
|
| 104 |
if "cough" in text or "difficulty breathing" in text:
|
| 105 |
-
feedback.append("
|
| 106 |
-
|
| 107 |
-
feedback.append("
|
| 108 |
-
|
| 109 |
-
feedback.append("
|
| 110 |
return "\n".join(feedback)
|
| 111 |
|
| 112 |
def analyze_voice(audio_file=None):
|
|
@@ -126,7 +132,7 @@ def analyze_voice(audio_file=None):
|
|
| 126 |
|
| 127 |
# Transcribe audio for symptom analysis
|
| 128 |
transcription = transcribe_audio(audio)
|
| 129 |
-
symptom_feedback = analyze_symptoms(transcription) if transcription else "No transcription available
|
| 130 |
|
| 131 |
# Analyze voice features for health indicators
|
| 132 |
feedback = []
|
|
@@ -135,17 +141,17 @@ def analyze_voice(audio_file=None):
|
|
| 135 |
|
| 136 |
# Rule-based analysis (thresholds from voice pathology studies)
|
| 137 |
if respiratory_score > 1.0:
|
| 138 |
-
feedback.append(f"
|
| 139 |
if mental_health_score > 5.0:
|
| 140 |
-
feedback.append(f"
|
| 141 |
if features["energy"] < 0.01:
|
| 142 |
-
feedback.append(f"
|
| 143 |
|
| 144 |
-
if not feedback:
|
| 145 |
-
feedback.append("
|
| 146 |
|
| 147 |
# Combine voice and symptom feedback
|
| 148 |
-
feedback.append("\n**Symptom
|
| 149 |
feedback.append(symptom_feedback)
|
| 150 |
feedback.append("\n**Voice Analysis Details**:")
|
| 151 |
feedback.append(f"Pitch: {features['pitch']:.2f} Hz (average fundamental frequency)")
|
|
@@ -191,9 +197,9 @@ iface = gr.Interface(
|
|
| 191 |
inputs=gr.Audio(type="filepath", label="Record or Upload Your Voice (WAV, MP3, FLAC, 1+ sec)", format="wav"),
|
| 192 |
outputs=gr.Textbox(label="Health Assessment Results"),
|
| 193 |
title="Voice Health Analyzer",
|
| 194 |
-
description="Record or upload your voice (minimum 1 second) to receive preliminary health insights. Speak clearly in English about your symptoms."
|
| 195 |
)
|
| 196 |
|
| 197 |
if __name__ == "__main__":
|
| 198 |
-
logger.info("Starting Voice Health Analyzer at 12:
|
| 199 |
iface.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 61 |
raise ValueError("No voiced segments detected")
|
| 62 |
voiced_audio = np.concatenate(voiced_frames)
|
| 63 |
|
| 64 |
+
# Pitch (F0) with range validation
|
| 65 |
+
pitches, magnitudes = librosa.piptrack(y=voiced_audio, sr=sr, fmin=75, fmax=300) # Adult pitch range
|
| 66 |
+
valid_pitches = [p for p in pitches[magnitudes > 0] if 75 <= p <= 300]
|
| 67 |
pitch = np.mean(valid_pitches) if valid_pitches else 0
|
| 68 |
jitter = np.std(valid_pitches) / pitch if pitch and valid_pitches else 0
|
| 69 |
+
if jitter > 10: # Cap extreme jitter (possible noise)
|
| 70 |
+
jitter = 10
|
| 71 |
+
logger.warning("Jitter exceeds 10%, likely due to noise or distortion")
|
| 72 |
|
| 73 |
# Shimmer (amplitude variation)
|
| 74 |
amplitudes = librosa.feature.rms(y=voiced_audio, frame_length=2048, hop_length=512)[0]
|
| 75 |
shimmer = np.std(amplitudes) / np.mean(amplitudes) if np.mean(amplitudes) else 0
|
| 76 |
+
if shimmer > 10: # Cap extreme shimmer (possible noise)
|
| 77 |
+
shimmer = 10
|
| 78 |
+
logger.warning("Shimmer exceeds 10%, likely due to noise or distortion")
|
| 79 |
|
| 80 |
# Energy
|
| 81 |
energy = np.mean(librosa.feature.rms(y=voiced_audio, frame_length=2048, hop_length=512)[0])
|
|
|
|
| 108 |
text = text.lower()
|
| 109 |
feedback = []
|
| 110 |
if "cough" in text or "difficulty breathing" in text:
|
| 111 |
+
feedback.append("Your voice suggests possible respiratory issues, such as bronchitis or asthma. Please consult a doctor.")
|
| 112 |
+
elif "stressed" in text or "stress" in text or "tired" in text or "fatigue" in text:
|
| 113 |
+
feedback.append("Your voice and words indicate possible stress or fatigue, which may relate to anxiety or exhaustion. Consider seeking medical advice.")
|
| 114 |
+
else:
|
| 115 |
+
feedback.append("Your input didn’t specify clear symptoms. For a comprehensive health check, please describe any issues (e.g., cough, stress) and consult a healthcare provider.")
|
| 116 |
return "\n".join(feedback)
|
| 117 |
|
| 118 |
def analyze_voice(audio_file=None):
|
|
|
|
| 132 |
|
| 133 |
# Transcribe audio for symptom analysis
|
| 134 |
transcription = transcribe_audio(audio)
|
| 135 |
+
symptom_feedback = analyze_symptoms(transcription) if transcription else "No transcription available. Please record again with clear speech."
|
| 136 |
|
| 137 |
# Analyze voice features for health indicators
|
| 138 |
feedback = []
|
|
|
|
| 141 |
|
| 142 |
# Rule-based analysis (thresholds from voice pathology studies)
|
| 143 |
if respiratory_score > 1.0:
|
| 144 |
+
feedback.append(f"Your voice shows elevated jitter ({respiratory_score:.2f}%), which may indicate respiratory issues like vocal cord irregularities. Consult a doctor.")
|
| 145 |
if mental_health_score > 5.0:
|
| 146 |
+
feedback.append(f"Your voice exhibits elevated shimmer ({mental_health_score:.2f}%), suggesting possible stress or emotional strain. Consider a health check.")
|
| 147 |
if features["energy"] < 0.01:
|
| 148 |
+
feedback.append(f"Your vocal energy is low ({features['energy']:.4f}), which might suggest fatigue. Seek medical advice if persistent.")
|
| 149 |
|
| 150 |
+
if not feedback and not symptom_feedback.startswith("No transcription"):
|
| 151 |
+
feedback.append("Your voice shows no significant health indicators based on current analysis.")
|
| 152 |
|
| 153 |
# Combine voice and symptom feedback
|
| 154 |
+
feedback.append("\n**Symptom Feedback (from your words)**:")
|
| 155 |
feedback.append(symptom_feedback)
|
| 156 |
feedback.append("\n**Voice Analysis Details**:")
|
| 157 |
feedback.append(f"Pitch: {features['pitch']:.2f} Hz (average fundamental frequency)")
|
|
|
|
| 197 |
inputs=gr.Audio(type="filepath", label="Record or Upload Your Voice (WAV, MP3, FLAC, 1+ sec)", format="wav"),
|
| 198 |
outputs=gr.Textbox(label="Health Assessment Results"),
|
| 199 |
title="Voice Health Analyzer",
|
| 200 |
+
description="Record or upload your voice (minimum 1 second) to receive preliminary health insights. Speak clearly in English about your symptoms (e.g., 'I have a cough' or 'I feel stressed')."
|
| 201 |
)
|
| 202 |
|
| 203 |
if __name__ == "__main__":
|
| 204 |
+
logger.info("Starting Voice Health Analyzer at 12:21 PM IST, June 23, 2025")
|
| 205 |
iface.launch(server_name="0.0.0.0", server_port=7860)
|