Spaces:
Sleeping
Sleeping
| 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) | |