Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -79,6 +79,8 @@ EMOTION_LABELS = [
|
|
| 79 |
"sadness",
|
| 80 |
"anger",
|
| 81 |
"fear",
|
|
|
|
|
|
|
| 82 |
"love",
|
| 83 |
"surprise",
|
| 84 |
"calm",
|
|
@@ -305,13 +307,61 @@ def detect_negation(text):
|
|
| 305 |
return False
|
| 306 |
|
| 307 |
def detect_crisis_keywords(text):
|
| 308 |
-
"""Detect crisis/emergency keywords"""
|
| 309 |
crisis_keywords = [
|
| 310 |
-
|
| 311 |
-
'
|
| 312 |
-
'
|
| 313 |
-
'
|
| 314 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
]
|
| 316 |
|
| 317 |
text_lower = text.lower()
|
|
@@ -320,6 +370,57 @@ def detect_crisis_keywords(text):
|
|
| 320 |
return True
|
| 321 |
return False
|
| 322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
def detect_mixed_emotions(text, prosodic_features):
|
| 324 |
"""Detect mixed emotions"""
|
| 325 |
text_lower = text.lower()
|
|
@@ -440,8 +541,8 @@ def enhanced_sentiment_analysis(text, prosodic_features, raw_results):
|
|
| 440 |
|
| 441 |
return sentiment_scores, final_confidence, is_mixed
|
| 442 |
|
| 443 |
-
def process_emotion_results(emotion_result):
|
| 444 |
-
"""Process zero-shot emotion classification results"""
|
| 445 |
if emotion_result is None or isinstance(emotion_result, Exception):
|
| 446 |
print(f"⚠️ Emotion classification error: {emotion_result}")
|
| 447 |
return {
|
|
@@ -451,15 +552,119 @@ def process_emotion_results(emotion_result):
|
|
| 451 |
"top_emotions": []
|
| 452 |
}
|
| 453 |
|
| 454 |
-
# Get
|
| 455 |
labels = emotion_result['labels']
|
| 456 |
scores = emotion_result['scores']
|
| 457 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 458 |
top_emotions = []
|
| 459 |
-
for i in range(min(5, len(
|
| 460 |
top_emotions.append({
|
| 461 |
-
"emotion":
|
| 462 |
-
"score": round(
|
| 463 |
})
|
| 464 |
|
| 465 |
primary_emotion = top_emotions[0]["emotion"] if top_emotions else "unknown"
|
|
@@ -555,8 +760,12 @@ def predict(audio_filepath):
|
|
| 555 |
sentiment_result
|
| 556 |
)
|
| 557 |
|
| 558 |
-
# Process emotion
|
| 559 |
-
emotion_data = process_emotion_results(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
|
| 561 |
print(f"✅ Detected Emotion: {emotion_data['primary']}")
|
| 562 |
print(f"✅ Sentiment: {max(sentiment_scores, key=sentiment_scores.get)}")
|
|
@@ -579,8 +788,13 @@ def predict(audio_filepath):
|
|
| 579 |
"analysis": {
|
| 580 |
"mixed_emotions": is_mixed,
|
| 581 |
"hindi_content_percentage": round(hindi_ratio * 100, 2),
|
| 582 |
-
"
|
| 583 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 584 |
},
|
| 585 |
"prosodic_features": {
|
| 586 |
"pitch_mean": round(prosodic_features['pitch_mean'], 2),
|
|
@@ -632,8 +846,10 @@ demo = gr.Interface(
|
|
| 632 |
|
| 633 |
### ✨ Features:
|
| 634 |
- **🎙️ Indic Conformer 600M** - State-of-the-art multilingual ASR
|
| 635 |
-
- **🎭 Zero-Shot Emotion Detection** -
|
| 636 |
- **💭 Sentiment Analysis** - Positive/Neutral/Negative classification
|
|
|
|
|
|
|
| 637 |
- **⚡ Optimized Processing** - 2-3x faster with batch feature extraction
|
| 638 |
- **🎵 Voice Analysis** - Fast pitch (PYIN), energy, and spectral features
|
| 639 |
- **🌐 Hinglish Support** - Works with Hindi + English mix
|
|
@@ -666,8 +882,13 @@ demo = gr.Interface(
|
|
| 666 |
"analysis": {
|
| 667 |
"mixed_emotions": false,
|
| 668 |
"hindi_content_percentage": 100.0,
|
| 669 |
-
"
|
| 670 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 671 |
},
|
| 672 |
"prosodic_features": {
|
| 673 |
"pitch_mean": 180.45,
|
|
@@ -679,18 +900,46 @@ demo = gr.Interface(
|
|
| 679 |
}
|
| 680 |
```
|
| 681 |
|
| 682 |
-
### 🎯 Supported Emotions (
|
| 683 |
- **Positive**: joy, happiness, love, excitement, calm
|
| 684 |
-
- **Negative**: sadness, anger, fear, frustration
|
| 685 |
- **Neutral**: neutral, surprise
|
| 686 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 687 |
### 🧪 Test Examples:
|
| 688 |
- **😊 Joy**: "मैं बहुत खुश हूं आज"
|
| 689 |
- **😢 Sadness**: "मुझे बहुत दुख हो रहा है"
|
| 690 |
- **😠 Anger**: "मुझे बहुत गुस्सा आ रहा है"
|
| 691 |
- **😨 Fear**: "मुझे डर लग रहा है"
|
| 692 |
-
-
|
| 693 |
-
-
|
|
|
|
|
|
|
| 694 |
|
| 695 |
### 💡 API Usage:
|
| 696 |
|
|
@@ -713,10 +962,34 @@ demo = gr.Interface(
|
|
| 713 |
```
|
| 714 |
|
| 715 |
**Performance Optimizations:**
|
| 716 |
-
- ⚡ 2-3x faster emotion classification (
|
| 717 |
- 🎵 3-5x faster pitch detection (PYIN vs piptrack)
|
| 718 |
- 💾 Cached audio resampler (no redundant object creation)
|
| 719 |
- 📊 Batch spectral feature extraction (single STFT pass)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 720 |
""",
|
| 721 |
theme=gr.themes.Soft(),
|
| 722 |
flagging_mode="never",
|
|
|
|
| 79 |
"sadness",
|
| 80 |
"anger",
|
| 81 |
"fear",
|
| 82 |
+
"distress", # Added for better crisis detection
|
| 83 |
+
"panic", # Added for emergency situations
|
| 84 |
"love",
|
| 85 |
"surprise",
|
| 86 |
"calm",
|
|
|
|
| 307 |
return False
|
| 308 |
|
| 309 |
def detect_crisis_keywords(text):
|
| 310 |
+
"""Detect crisis/emergency keywords - Comprehensive detection"""
|
| 311 |
crisis_keywords = [
|
| 312 |
+
# Violence & Assault - हिंसा और हमला
|
| 313 |
+
'बचाओ', 'मदद', 'help', 'save', 'rescue',
|
| 314 |
+
'मार', 'मारो', 'पीट', 'पिट', 'हिंसा', 'beat', 'beating', 'hit', 'hitting', 'violence', 'violent',
|
| 315 |
+
'थप्पड़', 'लात', 'घूंसा', 'slap', 'kick', 'punch',
|
| 316 |
+
'हमला', 'attack', 'attacking', 'assault',
|
| 317 |
+
'चाकू', 'बंदूक', 'हथियार', 'knife', 'gun', 'weapon',
|
| 318 |
+
|
| 319 |
+
# Fear & Danger - डर और खतरा
|
| 320 |
+
'डर', 'डरना', 'भय', 'fear', 'scared', 'afraid', 'terrified',
|
| 321 |
+
'खतरा', 'संकट', 'danger', 'dangerous', 'threat', 'emergency',
|
| 322 |
+
'भागो', 'run', 'escape',
|
| 323 |
+
|
| 324 |
+
# Death & Severe Harm - मृत्यु और गंभीर नुकसान
|
| 325 |
+
'मर', 'मरना', 'मार डाल', 'मौत', 'death', 'die', 'dying', 'kill', 'murder',
|
| 326 |
+
'खून', 'blood', 'bleeding',
|
| 327 |
+
'जान', 'life',
|
| 328 |
+
|
| 329 |
+
# Distress Calls - संकट संकेत
|
| 330 |
+
'छोड़', 'छोड़ो', 'जाने दो', 'leave', 'leave me', 'let go', 'stop', 'please stop',
|
| 331 |
+
'नहीं नहीं', 'मत करो', 'no no', "don't", 'stop it',
|
| 332 |
+
'कोई है', 'anyone', 'somebody help',
|
| 333 |
+
|
| 334 |
+
# Kidnapping & Abduction - अपहरण
|
| 335 |
+
'उठा', 'ले जा', 'kidnap', 'abduct', 'taken',
|
| 336 |
+
'छुड़ा', 'free me', 'release',
|
| 337 |
+
|
| 338 |
+
# Medical Emergency - चिकित्सा आपातकाल
|
| 339 |
+
'दर्द', 'तकलीफ', 'pain', 'hurt', 'hurting', 'ache',
|
| 340 |
+
'सांस', 'साँस', 'breath', 'breathing', 'suffocate',
|
| 341 |
+
'दिल', 'हृदय', 'heart', 'chest pain', 'heart attack',
|
| 342 |
+
'दौरा', 'बेहोश', 'seizure', 'unconscious', 'faint',
|
| 343 |
+
'खून बह', 'bleeding', 'injury', 'injured',
|
| 344 |
+
'एम्बुलेंस', 'अस्पताल', 'डॉक्टर', 'ambulance', 'hospital', 'doctor',
|
| 345 |
+
'दवा', 'दवाई', 'medicine', 'medication',
|
| 346 |
+
|
| 347 |
+
# Suicide & Self-Harm - आत्महत्या
|
| 348 |
+
'आत्महत्या', 'suicide', 'kill myself',
|
| 349 |
+
'मर जा', 'जीना नहीं', 'want to die', "don't want to live",
|
| 350 |
+
'ख़त्म', 'समाप्त', 'end it', 'end this',
|
| 351 |
+
|
| 352 |
+
# Abuse & Harassment - दुर्व्यवहार
|
| 353 |
+
'बलात्कार', 'छेड़', 'rape', 'molest', 'harassment', 'abuse',
|
| 354 |
+
'गलत काम', 'छूना', 'touch', 'inappropriate',
|
| 355 |
+
|
| 356 |
+
# Accidents - दुर्घटना
|
| 357 |
+
'दुर्घटना', 'accident', 'crash', 'fell', 'fall',
|
| 358 |
+
'आग', 'fire', 'smoke', 'burning',
|
| 359 |
+
'बिजली', 'electric', 'shock',
|
| 360 |
+
|
| 361 |
+
# Panic & Severe Distress - घबराहट
|
| 362 |
+
'घबरा', 'panic', 'panicking',
|
| 363 |
+
'बचा नहीं', 'फंस', 'trapped', 'stuck',
|
| 364 |
+
'सहारा', 'support', 'need help'
|
| 365 |
]
|
| 366 |
|
| 367 |
text_lower = text.lower()
|
|
|
|
| 370 |
return True
|
| 371 |
return False
|
| 372 |
|
| 373 |
+
def detect_mental_health_distress(text):
|
| 374 |
+
"""Detect mental health crisis indicators"""
|
| 375 |
+
mental_health_keywords = [
|
| 376 |
+
# Depression - अवसाद
|
| 377 |
+
'अवसाद', 'डिप्रेशन', 'depression', 'depressed',
|
| 378 |
+
'उदास', 'निराश', 'hopeless', 'helpless',
|
| 379 |
+
'कोई फायदा नहीं', 'no point', 'pointless', 'worthless',
|
| 380 |
+
|
| 381 |
+
# Anxiety - चिंता
|
| 382 |
+
'घबराहट', 'बेचैन', 'anxiety', 'anxious', 'worried sick',
|
| 383 |
+
'चिंता', 'टेंशन', 'stress', 'stressed',
|
| 384 |
+
'परेशान', 'troubled', 'disturbed',
|
| 385 |
+
|
| 386 |
+
# Isolation - अलगाव
|
| 387 |
+
'अकेला', 'तन्हा', 'lonely', 'alone', 'isolated',
|
| 388 |
+
'कोई नहीं', 'no one', 'nobody cares',
|
| 389 |
+
|
| 390 |
+
# Despair - निराशा
|
| 391 |
+
'हार', 'give up', 'giving up',
|
| 392 |
+
'कोशिश नहीं', "can't anymore", 'too much',
|
| 393 |
+
'थक', 'tired of', 'exhausted'
|
| 394 |
+
]
|
| 395 |
+
|
| 396 |
+
text_lower = text.lower()
|
| 397 |
+
count = sum(1 for keyword in mental_health_keywords if keyword in text_lower)
|
| 398 |
+
return count >= 2 # Require at least 2 indicators for mental health flag
|
| 399 |
+
|
| 400 |
+
def detect_grief_loss(text):
|
| 401 |
+
"""Detect grief and loss situations"""
|
| 402 |
+
grief_keywords = [
|
| 403 |
+
'चल बसा', 'गुज़र', 'खो दिया', 'died', 'passed away', 'lost',
|
| 404 |
+
'अंतिम संस्कार', 'funeral', 'cremation',
|
| 405 |
+
'याद', 'miss', 'missing',
|
| 406 |
+
'गम', 'शोक', 'grief', 'mourning', 'sorrow'
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
text_lower = text.lower()
|
| 410 |
+
return any(keyword in text_lower for keyword in grief_keywords)
|
| 411 |
+
|
| 412 |
+
def detect_relationship_distress(text):
|
| 413 |
+
"""Detect relationship problems"""
|
| 414 |
+
relationship_keywords = [
|
| 415 |
+
'तलाक', 'अलग', 'divorce', 'separation', 'breakup', 'broke up',
|
| 416 |
+
'धोखा', 'बेवफा', 'cheat', 'cheating', 'betrayal',
|
| 417 |
+
'लड़ाई', 'झगड़ा', 'fight', 'fighting', 'argument',
|
| 418 |
+
'छोड़ दिया', 'left me', 'abandoned'
|
| 419 |
+
]
|
| 420 |
+
|
| 421 |
+
text_lower = text.lower()
|
| 422 |
+
return any(keyword in text_lower for keyword in relationship_keywords)
|
| 423 |
+
|
| 424 |
def detect_mixed_emotions(text, prosodic_features):
|
| 425 |
"""Detect mixed emotions"""
|
| 426 |
text_lower = text.lower()
|
|
|
|
| 541 |
|
| 542 |
return sentiment_scores, final_confidence, is_mixed
|
| 543 |
|
| 544 |
+
def process_emotion_results(emotion_result, transcription, prosodic_features=None):
|
| 545 |
+
"""Process zero-shot emotion classification results with multi-situation awareness"""
|
| 546 |
if emotion_result is None or isinstance(emotion_result, Exception):
|
| 547 |
print(f"⚠️ Emotion classification error: {emotion_result}")
|
| 548 |
return {
|
|
|
|
| 552 |
"top_emotions": []
|
| 553 |
}
|
| 554 |
|
| 555 |
+
# Get emotions and scores
|
| 556 |
labels = emotion_result['labels']
|
| 557 |
scores = emotion_result['scores']
|
| 558 |
|
| 559 |
+
# Create emotion score dictionary for manipulation
|
| 560 |
+
emotion_scores = {labels[i]: scores[i] for i in range(len(labels))}
|
| 561 |
+
|
| 562 |
+
# SITUATION DETECTION
|
| 563 |
+
is_crisis = detect_crisis_keywords(transcription)
|
| 564 |
+
is_mental_health = detect_mental_health_distress(transcription)
|
| 565 |
+
is_grief = detect_grief_loss(transcription)
|
| 566 |
+
is_relationship = detect_relationship_distress(transcription)
|
| 567 |
+
|
| 568 |
+
# CRISIS DETECTION OVERRIDE - Highest priority for emergency situations
|
| 569 |
+
if is_crisis:
|
| 570 |
+
print("🚨 CRISIS DETECTED - Adjusting emotion predictions")
|
| 571 |
+
|
| 572 |
+
# Strongly boost fear and related crisis emotions
|
| 573 |
+
crisis_emotions = ['fear', 'distress', 'panic', 'anger', 'sadness']
|
| 574 |
+
boost_factor = 4.0
|
| 575 |
+
|
| 576 |
+
for emotion in crisis_emotions:
|
| 577 |
+
if emotion in emotion_scores:
|
| 578 |
+
emotion_scores[emotion] = min(0.95, emotion_scores[emotion] * boost_factor)
|
| 579 |
+
|
| 580 |
+
# Suppress inappropriate emotions for crisis situations
|
| 581 |
+
suppress_emotions = ['surprise', 'excitement', 'happiness', 'joy', 'calm']
|
| 582 |
+
suppress_factor = 0.15
|
| 583 |
+
|
| 584 |
+
for emotion in suppress_emotions:
|
| 585 |
+
if emotion in emotion_scores:
|
| 586 |
+
emotion_scores[emotion] = max(0.01, emotion_scores[emotion] * suppress_factor)
|
| 587 |
+
|
| 588 |
+
# Renormalize scores
|
| 589 |
+
total = sum(emotion_scores.values())
|
| 590 |
+
if total > 0:
|
| 591 |
+
emotion_scores = {k: v/total for k, v in emotion_scores.items()}
|
| 592 |
+
|
| 593 |
+
# MENTAL HEALTH DISTRESS - Boost sadness, fear, reduce positive
|
| 594 |
+
elif is_mental_health:
|
| 595 |
+
print("🧠 Mental health distress detected - Adjusting predictions")
|
| 596 |
+
|
| 597 |
+
mental_health_emotions = ['sadness', 'fear', 'frustration', 'neutral']
|
| 598 |
+
boost_factor = 2.0
|
| 599 |
+
|
| 600 |
+
for emotion in mental_health_emotions:
|
| 601 |
+
if emotion in emotion_scores:
|
| 602 |
+
emotion_scores[emotion] = min(0.90, emotion_scores[emotion] * boost_factor)
|
| 603 |
+
|
| 604 |
+
# Reduce positive emotions
|
| 605 |
+
suppress_emotions = ['happiness', 'joy', 'excitement', 'calm']
|
| 606 |
+
for emotion in suppress_emotions:
|
| 607 |
+
if emotion in emotion_scores:
|
| 608 |
+
emotion_scores[emotion] = max(0.05, emotion_scores[emotion] * 0.3)
|
| 609 |
+
|
| 610 |
+
total = sum(emotion_scores.values())
|
| 611 |
+
if total > 0:
|
| 612 |
+
emotion_scores = {k: v/total for k, v in emotion_scores.items()}
|
| 613 |
+
|
| 614 |
+
# GRIEF & LOSS - Boost sadness primarily
|
| 615 |
+
elif is_grief:
|
| 616 |
+
print("💔 Grief/loss detected - Adjusting predictions")
|
| 617 |
+
|
| 618 |
+
if 'sadness' in emotion_scores:
|
| 619 |
+
emotion_scores['sadness'] = min(0.85, emotion_scores['sadness'] * 2.5)
|
| 620 |
+
|
| 621 |
+
# Moderate boost for related emotions
|
| 622 |
+
if 'neutral' in emotion_scores:
|
| 623 |
+
emotion_scores['neutral'] = min(0.40, emotion_scores['neutral'] * 1.3)
|
| 624 |
+
|
| 625 |
+
# Suppress joy/excitement
|
| 626 |
+
suppress_emotions = ['happiness', 'joy', 'excitement']
|
| 627 |
+
for emotion in suppress_emotions:
|
| 628 |
+
if emotion in emotion_scores:
|
| 629 |
+
emotion_scores[emotion] = max(0.02, emotion_scores[emotion] * 0.2)
|
| 630 |
+
|
| 631 |
+
total = sum(emotion_scores.values())
|
| 632 |
+
if total > 0:
|
| 633 |
+
emotion_scores = {k: v/total for k, v in emotion_scores.items()}
|
| 634 |
+
|
| 635 |
+
# RELATIONSHIP DISTRESS - Boost sadness, anger, frustration
|
| 636 |
+
elif is_relationship:
|
| 637 |
+
print("💔 Relationship distress detected - Adjusting predictions")
|
| 638 |
+
|
| 639 |
+
relationship_emotions = ['sadness', 'anger', 'frustration']
|
| 640 |
+
boost_factor = 1.8
|
| 641 |
+
|
| 642 |
+
for emotion in relationship_emotions:
|
| 643 |
+
if emotion in emotion_scores:
|
| 644 |
+
emotion_scores[emotion] = min(0.80, emotion_scores[emotion] * boost_factor)
|
| 645 |
+
|
| 646 |
+
total = sum(emotion_scores.values())
|
| 647 |
+
if total > 0:
|
| 648 |
+
emotion_scores = {k: v/total for k, v in emotion_scores.items()}
|
| 649 |
+
|
| 650 |
+
# PROSODIC ADJUSTMENT - High pitch variation + negative words = likely anger/fear
|
| 651 |
+
if prosodic_features and prosodic_features.get('pitch_std', 0) > 40:
|
| 652 |
+
negative_words = ['गुस्सा', 'क्रोध', 'नफरत', 'angry', 'mad', 'hate']
|
| 653 |
+
if any(word in transcription.lower() for word in negative_words):
|
| 654 |
+
if 'anger' in emotion_scores:
|
| 655 |
+
emotion_scores['anger'] = min(0.90, emotion_scores['anger'] * 1.5)
|
| 656 |
+
total = sum(emotion_scores.values())
|
| 657 |
+
if total > 0:
|
| 658 |
+
emotion_scores = {k: v/total for k, v in emotion_scores.items()}
|
| 659 |
+
|
| 660 |
+
# Sort by score and create top emotions list
|
| 661 |
+
sorted_emotions = sorted(emotion_scores.items(), key=lambda x: x[1], reverse=True)
|
| 662 |
+
|
| 663 |
top_emotions = []
|
| 664 |
+
for i in range(min(5, len(sorted_emotions))):
|
| 665 |
top_emotions.append({
|
| 666 |
+
"emotion": sorted_emotions[i][0],
|
| 667 |
+
"score": round(sorted_emotions[i][1], 4)
|
| 668 |
})
|
| 669 |
|
| 670 |
primary_emotion = top_emotions[0]["emotion"] if top_emotions else "unknown"
|
|
|
|
| 760 |
sentiment_result
|
| 761 |
)
|
| 762 |
|
| 763 |
+
# Process emotion with crisis awareness
|
| 764 |
+
emotion_data = process_emotion_results(
|
| 765 |
+
emotion_result,
|
| 766 |
+
transcription,
|
| 767 |
+
prosodic_features
|
| 768 |
+
)
|
| 769 |
|
| 770 |
print(f"✅ Detected Emotion: {emotion_data['primary']}")
|
| 771 |
print(f"✅ Sentiment: {max(sentiment_scores, key=sentiment_scores.get)}")
|
|
|
|
| 788 |
"analysis": {
|
| 789 |
"mixed_emotions": is_mixed,
|
| 790 |
"hindi_content_percentage": round(hindi_ratio * 100, 2),
|
| 791 |
+
"has_negation": detect_negation(transcription),
|
| 792 |
+
"situations": {
|
| 793 |
+
"is_crisis": detect_crisis_keywords(transcription),
|
| 794 |
+
"is_mental_health_distress": detect_mental_health_distress(transcription),
|
| 795 |
+
"is_grief_loss": detect_grief_loss(transcription),
|
| 796 |
+
"is_relationship_distress": detect_relationship_distress(transcription)
|
| 797 |
+
}
|
| 798 |
},
|
| 799 |
"prosodic_features": {
|
| 800 |
"pitch_mean": round(prosodic_features['pitch_mean'], 2),
|
|
|
|
| 846 |
|
| 847 |
### ✨ Features:
|
| 848 |
- **🎙️ Indic Conformer 600M** - State-of-the-art multilingual ASR
|
| 849 |
+
- **🎭 Zero-Shot Emotion Detection** - 13 emotions using joeddav/xlm-roberta-large-xnli
|
| 850 |
- **💭 Sentiment Analysis** - Positive/Neutral/Negative classification
|
| 851 |
+
- **🚨 Multi-Situation Awareness** - Detects crisis, mental health, grief, relationship distress
|
| 852 |
+
- **🧠 Context-Aware Adjustment** - Emotions adjusted based on detected situations
|
| 853 |
- **⚡ Optimized Processing** - 2-3x faster with batch feature extraction
|
| 854 |
- **🎵 Voice Analysis** - Fast pitch (PYIN), energy, and spectral features
|
| 855 |
- **🌐 Hinglish Support** - Works with Hindi + English mix
|
|
|
|
| 882 |
"analysis": {
|
| 883 |
"mixed_emotions": false,
|
| 884 |
"hindi_content_percentage": 100.0,
|
| 885 |
+
"has_negation": false,
|
| 886 |
+
"situations": {
|
| 887 |
+
"is_crisis": false,
|
| 888 |
+
"is_mental_health_distress": false,
|
| 889 |
+
"is_grief_loss": false,
|
| 890 |
+
"is_relationship_distress": false
|
| 891 |
+
}
|
| 892 |
},
|
| 893 |
"prosodic_features": {
|
| 894 |
"pitch_mean": 180.45,
|
|
|
|
| 900 |
}
|
| 901 |
```
|
| 902 |
|
| 903 |
+
### 🎯 Supported Emotions (13):
|
| 904 |
- **Positive**: joy, happiness, love, excitement, calm
|
| 905 |
+
- **Negative**: sadness, anger, fear, distress, panic, frustration
|
| 906 |
- **Neutral**: neutral, surprise
|
| 907 |
|
| 908 |
+
### 🎯 Situation Detection:
|
| 909 |
+
|
| 910 |
+
**🚨 Crisis/Emergency:**
|
| 911 |
+
- Violence, assault, abuse
|
| 912 |
+
- Medical emergencies
|
| 913 |
+
- Suicide/self-harm
|
| 914 |
+
- Accidents, fire, danger
|
| 915 |
+
- Keywords: बचाओ, मदद, मार, खून, दर्द, आग, etc.
|
| 916 |
+
|
| 917 |
+
**🧠 Mental Health Distress:**
|
| 918 |
+
- Depression, anxiety
|
| 919 |
+
- Hopelessness, isolation
|
| 920 |
+
- Requires 2+ indicators
|
| 921 |
+
- Keywords: अवसाद, अकेला, निराश, थक गया, etc.
|
| 922 |
+
|
| 923 |
+
**💔 Grief & Loss:**
|
| 924 |
+
- Death of loved ones
|
| 925 |
+
- Mourning, sorrow
|
| 926 |
+
- Keywords: गुज़र गया, खो दिया, याद आती है, etc.
|
| 927 |
+
|
| 928 |
+
**💔 Relationship Distress:**
|
| 929 |
+
- Breakup, divorce
|
| 930 |
+
- Betrayal, cheating
|
| 931 |
+
- Conflict, arguments
|
| 932 |
+
- Keywords: तलाक, धोखा, झगड़ा, छोड़ दिया, etc.
|
| 933 |
+
|
| 934 |
### 🧪 Test Examples:
|
| 935 |
- **😊 Joy**: "मैं बहुत खुश हूं आज"
|
| 936 |
- **😢 Sadness**: "मुझे बहुत दुख हो रहा है"
|
| 937 |
- **😠 Anger**: "मुझे बहुत गुस्सा आ रहा है"
|
| 938 |
- **😨 Fear**: "मुझे डर लग रहा है"
|
| 939 |
+
- **🚨 Crisis**: "बचाओ बचाओ मुझे कोई मदद करो"
|
| 940 |
+
- **🧠 Mental Health**: "मैं बहुत अकेला और निराश महसूस कर रहा हूं"
|
| 941 |
+
- **💔 Grief**: "मेरे पिताजी गुज़र गए, बहुत याद आती है"
|
| 942 |
+
- **💔 Relationship**: "मेरी पत्नी ने मुझे छोड़ दिया, बहुत दुख है"
|
| 943 |
|
| 944 |
### 💡 API Usage:
|
| 945 |
|
|
|
|
| 962 |
```
|
| 963 |
|
| 964 |
**Performance Optimizations:**
|
| 965 |
+
- ⚡ 2-3x faster emotion classification (optimized to 13 labels)
|
| 966 |
- 🎵 3-5x faster pitch detection (PYIN vs piptrack)
|
| 967 |
- 💾 Cached audio resampler (no redundant object creation)
|
| 968 |
- 📊 Batch spectral feature extraction (single STFT pass)
|
| 969 |
+
|
| 970 |
+
**🚨 Multi-Situation Awareness:**
|
| 971 |
+
|
| 972 |
+
**Crisis Detection (4x boost):**
|
| 973 |
+
- 100+ emergency keywords in Hindi/English
|
| 974 |
+
- Violence, medical, suicide, accidents, fire
|
| 975 |
+
- Boosts: fear, distress, panic, anger
|
| 976 |
+
- Suppresses: surprise, excitement, joy (85%)
|
| 977 |
+
|
| 978 |
+
**Mental Health (2x boost):**
|
| 979 |
+
- Depression, anxiety, isolation indicators
|
| 980 |
+
- Requires 2+ keywords for detection
|
| 981 |
+
- Boosts: sadness, fear, frustration
|
| 982 |
+
- Suppresses: happiness, excitement (70%)
|
| 983 |
+
|
| 984 |
+
**Grief/Loss (2.5x boost):**
|
| 985 |
+
- Death, mourning, bereavement
|
| 986 |
+
- Boosts: sadness primarily
|
| 987 |
+
- Suppresses: joy, excitement (80%)
|
| 988 |
+
|
| 989 |
+
**Relationship Distress (1.8x boost):**
|
| 990 |
+
- Breakup, divorce, betrayal
|
| 991 |
+
- Boosts: sadness, anger, frustration
|
| 992 |
+
- Maintains nuanced emotional detection
|
| 993 |
""",
|
| 994 |
theme=gr.themes.Soft(),
|
| 995 |
flagging_mode="never",
|