File size: 7,678 Bytes
a1edd2e
 
 
2f6d242
a1edd2e
2f6d242
9a52092
2f6d242
88ceca6
 
a1edd2e
2f6d242
 
 
a1edd2e
2f6d242
 
 
 
 
 
 
 
 
a1edd2e
 
2f6d242
 
 
9a52092
4be042b
5a60f42
88ceca6
9a52092
 
 
 
67b7919
9a52092
5a60f42
a1edd2e
5a60f42
 
88ceca6
2f6d242
5a60f42
9a52092
2f6d242
 
9a52092
2f6d242
 
9a52092
 
 
2f6d242
a1edd2e
5a60f42
 
2f6d242
 
 
 
9a52092
 
5a60f42
9a52092
 
2f6d242
 
 
9a52092
 
 
5411775
 
9a52092
2f6d242
 
 
 
5a60f42
2f6d242
4e3aed3
2f6d242
68e24ff
 
9a52092
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67b7919
5a60f42
4e3aed3
5a60f42
2f6d242
 
 
9a52092
2f6d242
4e3aed3
 
2f6d242
 
 
a2e6bf6
4e3aed3
 
88ceca6
 
 
9a52092
88ceca6
9a52092
 
2f6d242
5a60f42
9a52092
67b7919
4e3aed3
 
 
 
 
 
2f6d242
a2e6bf6
4e3aed3
 
 
 
5a60f42
4e3aed3
 
 
5a60f42
 
 
4e3aed3
5a60f42
 
 
a2e6bf6
4e3aed3
9a52092
2f6d242
a2e6bf6
 
2f6d242
 
9a52092
4e3aed3
 
2f6d242
 
 
4e3aed3
 
 
a1edd2e
2f6d242
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import gradio as gr
from transformers import pipeline
from datetime import datetime
import random

# -------------------------------------------------
# 🎯 MODEL INITIALIZATION
# -------------------------------------------------
MODEL_NAME = "superb/hubert-large-superb-er"
emotion_classifier = pipeline("audio-classification", model=MODEL_NAME)

# -------------------------------------------------
# πŸ˜„ EMOTION MAP + COLORS
# -------------------------------------------------
EMOTION_MAP = {
    "ang": ("Angry", "😑", "#ff4d4d"),
    "hap": ("Happy", "πŸ˜„", "#4caf50"),
    "neu": ("Neutral", "😐", "#9e9e9e"),
    "sad": ("Sad", "😒", "#2196f3"),
    "exc": ("Excited", "🀩", "#ff9800"),
    "fru": ("Frustrated", "😀", "#f44336"),
    "fea": ("Fearful", "😨", "#673ab7"),
    "sur": ("Surprised", "😲", "#00bcd4"),
    "dis": ("Disgusted", "🀒", "#8bc34a"),
}

# -------------------------------------------------
# 🧠 EMOTION ANALYSIS
# -------------------------------------------------
def analyze_emotion(audio, team, purpose):
    if audio is None:
        return "<p style='color:red;'>⚠️ Please record or upload audio first.</p>", None

    if team == "Other":
        team = "Custom/Unspecified"
    if purpose == "Other":
        purpose = "Custom/Unspecified"

    results = emotion_classifier(audio)
    results = sorted(results, key=lambda x: x["score"], reverse=True)
    top = results[0]
    label, emoji, color = EMOTION_MAP.get(top["label"], (top["label"], "🎭", "#607d8b"))
    score = round(top["score"] * 100, 2)

    dashboard_html = f"""
    <div style="text-align:center; padding:15px;">
        <h2>🏒 <b>{team}</b> | 🎯 <b>{purpose}</b></h2>
        <h3 style="color:{color}; font-size:26px;">{emoji} {label.upper()} β€” {score}%</h3>
        <p style="color:#666;">Detected Emotion Intensity (Confidence)</p>
        <div style="width:85%; margin:auto; background:#eee; border-radius:20px;">
            <div style="width:{score}%; background:{color}; height:20px; border-radius:20px;"></div>
        </div>
        <br>
        <h4>πŸ“Š Full Emotion Breakdown</h4>
        <ul style="list-style:none; padding:0;">
    """
    for r in results:
        lbl, emo, clr = EMOTION_MAP.get(r["label"], (r["label"], "🎭", "#777"))
        scr = round(r["score"] * 100, 2)
        dashboard_html += f"<li>{emo} <b>{lbl}</b>: {scr}%</li>"
    dashboard_html += "</ul><hr>"

    insights = random.choice([
        "🧩 Team seems calm and balanced today. Great stability!",
        "⚑ Slight emotional tension detected. Consider quick sync-up meetings.",
        "πŸ’¬ High positive tone β€” keep up the good team energy!",
        "🚨 Stress indicators detected. HR may follow up proactively.",
        "πŸ“ˆ Emotion variation is rising β€” review workloads or deadlines."
    ])

    insight_html = f"""
    <div style="background:#f5f5f5; padding:15px; border-radius:12px;
                margin-top:15px; border-left:6px solid #4a90e2;
                box-shadow:0 2px 6px rgba(0,0,0,0.05);">
        <h4 style="color:#222; margin-bottom:6px;">🧠 AI Insight</h4>
        <p style="color:#333; font-size:16px; font-weight:500;">{insights}</p>
        <p style="font-size:13px; color:#777;">(Demo mode β€” not stored to any database)</p>
    </div>
    """
    return dashboard_html, insight_html


# -------------------------------------------------
# 🎨 GRADIO UI ELEMENTS
# -------------------------------------------------
DEPARTMENTS = ["Test","Procurement", "Logistics", "Planning", "Inventory", "Distribution", "HR", "Other"]
PURPOSES = ["Test","HR Meeting", "Team Stand-up", "One-on-One", "Customer Call", "Interview", "Other"]

disclaimer_html = """
<div style="display:flex; align-items:center; background:linear-gradient(135deg, #fff8e1, #fff3cd);
            padding:15px; border-radius:12px; margin-top:20px; border-left:8px solid #ff9800;
            box-shadow:0 2px 6px rgba(0,0,0,0.1);">
    <div style="font-size:28px; margin-right:12px; color:#ff9800;">πŸ’‘</div>
    <div>
        <h3 style="color:#d35400; margin:0 0 5px 0;">Demo Disclaimer</h3>
        <p style="color:#333; font-size:15px; line-height:1.6; margin:0;">
            This is a <b style="color:#e65100;">demonstration version</b> created for HR and leadership showcases.<br>
            Your voice data is 
            <b style="background-color:#fffbe6; color:#c0392b; padding:2px 6px; border-radius:4px;">
            NOT being saved or shared
            </b> anywhere.<br>
            Database logging is <b style="color:#e65100;">simulated</b> β€” you can record or upload audio freely.<br>
            βœ… Safe to explore and test in this environment.
        </p>
    </div>
</div>
"""

# -------------------------------------------------
# πŸš€ APP INTERFACE WITH INLINE LOADING
# -------------------------------------------------
with gr.Blocks(theme=gr.themes.Soft()) as app:
    gr.HTML("""
    <div style="text-align:center; padding:20px;">
        <h1>🎧 SCM Emotion Intelligence Dashboard</h1>
        <p style="font-size:16px; color:#555;">
            Analyze uploaded or recorded team meeting audio to understand the emotional tone of employees.<br>
            Built for HR and Managers to assess engagement and team well-being.
        </p>
    </div>
    """)

    with gr.Row(equal_height=True):
        with gr.Column(scale=1, min_width=380):
            audio_input = gr.Audio(
                sources=["microphone", "upload"],
                type="filepath",
                label="πŸŽ™οΈ Record or Upload Audio",
            )
            team_input = gr.Dropdown(DEPARTMENTS, label="🏒 Select Team / Department")
            purpose_input = gr.Dropdown(PURPOSES, label="🎯 Purpose of Audio")
            analyze_btn = gr.Button("πŸš€ Analyze Emotion", variant="primary")

            gr.HTML(disclaimer_html)

        with gr.Column(scale=2, min_width=550):
            output_html = gr.HTML("""
                <div style='text-align:center; padding:30px; color:#999;'>
                    <p>Awaiting input... Upload or record to begin analysis.</p>
                </div>
            """)
            insight_html = gr.HTML()

    # Inline loader β€” replaces dashboard temporarily
    def process_with_loader(audio, team, purpose):
        loader_html = """
        <div style='text-align:center; padding:60px;'>
            <div style='margin:auto; border:6px solid #eee; border-top:6px solid #4a90e2;
                        border-radius:50%; width:50px; height:50px; animation:spin 1s linear infinite;'></div>
            <h3 style='color:#333; margin-top:20px;'>⏳ Analyzing your audio...</h3>
            <p style='color:#777;'>This may take a few seconds depending on file size.</p>
            <style>@keyframes spin {0%{transform:rotate(0deg);}100%{transform:rotate(360deg);}}</style>
        </div>
        """
        yield loader_html, None
        dashboard_html, insight_html = analyze_emotion(audio, team, purpose)
        yield dashboard_html, insight_html

    analyze_btn.click(
        fn=process_with_loader,
        inputs=[audio_input, team_input, purpose_input],
        outputs=[output_html, insight_html],
    )

    gr.HTML("""
    <hr>
    <p style="text-align:center; color:#999; font-size:14px;">
        πŸ’Ύ (Demo Mode) Database integration coming soon for Power BI visualization.<br>
        Presented by <b>Dhrubo Bhattacharjee</b>
    </p>
    """)

# -------------------------------------------------
# 🏁 LAUNCH APP
# -------------------------------------------------
if __name__ == "__main__":
    app.launch(server_name="0.0.0.0", server_port=7860)