MaroofTechSorcerer commited on
Commit
3cf77dc
Β·
verified Β·
1 Parent(s): 1505d12

Create app3.py

Browse files
Files changed (1) hide show
  1. app3.py +167 -0
app3.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ import tempfile
4
+ import whisper
5
+ from transformers import pipeline
6
+ import plotly.express as px
7
+ import torch
8
+ import logging
9
+ import warnings
10
+ import shutil
11
+
12
+ # Suppress warnings for a clean console
13
+ logging.getLogger("torch").setLevel(logging.CRITICAL)
14
+ logging.getLogger("transformers").setLevel(logging.CRITICAL)
15
+ warnings.filterwarnings("ignore")
16
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
+ torch.device("cpu")
18
+
19
+ # Set Streamlit app layout
20
+ st.set_page_config(layout="wide", page_title="Voice Based Sentiment Analysis")
21
+
22
+ # Interface design
23
+ st.title("πŸŽ™οΈ Voice Based Sentiment Analysis")
24
+ st.write("Detect emotions, sentiment, and sarcasm from your voice with high accuracy.")
25
+
26
+ # Sidebar for file upload
27
+ st.sidebar.title("Audio Input")
28
+ st.sidebar.write("Upload a WAV file for transcription and detailed analysis.")
29
+ audio_file = st.sidebar.file_uploader("Choose an audio file", type=["wav"], help="Supports WAV format only.")
30
+ upload_button = st.sidebar.button("Analyze", help="Click to process the uploaded audio.")
31
+
32
+ # Check if FFmpeg is available
33
+ def check_ffmpeg():
34
+ return shutil.which("ffmpeg") is not None
35
+
36
+ # Emotion Detection Function
37
+ @st.cache_resource
38
+ def get_emotion_classifier():
39
+ emotion_model = "bhadresh-savani/distilbert-base-uncased-emotion"
40
+ return pipeline("text-classification", model=emotion_model, top_k=None, device=-1)
41
+
42
+ def perform_emotion_detection(text):
43
+ try:
44
+ emotion_classifier = get_emotion_classifier()
45
+ emotion_results = emotion_classifier(text)[0]
46
+ emotion_map = {"anger": "😑", "fear": "😨", "joy": "😊", "love": "❀️", "sadness": "😒", "surprise": "😲"}
47
+ emotions_dict = {result['label']: result['score'] for result in emotion_results}
48
+ top_emotion = max(emotions_dict, key=emotions_dict.get)
49
+ sentiment_map = {"joy": "POSITIVE", "love": "POSITIVE", "anger": "NEGATIVE", "fear": "NEGATIVE", "sadness": "NEGATIVE", "surprise": "NEUTRAL"}
50
+ sentiment = sentiment_map.get(top_emotion, "NEUTRAL")
51
+ return emotions_dict, top_emotion, emotion_map, sentiment
52
+ except Exception as e:
53
+ st.error(f"Emotion detection failed: {str(e)}")
54
+ return {}, "unknown", {}, "UNKNOWN"
55
+
56
+ # Sarcasm Detection Function
57
+ @st.cache_resource
58
+ def get_sarcasm_classifier():
59
+ sarcasm_model = "cardiffnlp/twitter-roberta-base-irony"
60
+ return pipeline("text-classification", model=sarcasm_model, device=-1)
61
+
62
+ def perform_sarcasm_detection(text):
63
+ try:
64
+ sarcasm_classifier = get_sarcasm_classifier()
65
+ result = sarcasm_classifier(text)[0]
66
+ is_sarcastic = result['label'] == "LABEL_1"
67
+ sarcasm_score = result['score'] if is_sarcastic else 1 - result['score']
68
+ return is_sarcastic, sarcasm_score
69
+ except Exception as e:
70
+ st.error(f"Sarcasm detection failed: {str(e)}")
71
+ return False, 0.0
72
+
73
+ # Transcription Function with Whisper
74
+ @st.cache_resource
75
+ def get_whisper_model():
76
+ return whisper.load_model("base")
77
+
78
+ def transcribe_audio(audio_file):
79
+ if not check_ffmpeg():
80
+ st.error("FFmpeg is not installed or not found in PATH. Please install FFmpeg and add it to your system PATH.")
81
+ st.markdown("**Instructions to install FFmpeg on Windows:**\n"
82
+ "1. Download FFmpeg from [https://www.gyan.dev/ffmpeg/builds/](https://www.gyan.dev/ffmpeg/builds/) (e.g., `ffmpeg-release-essentials.zip`).\n"
83
+ "2. Extract the ZIP to a folder (e.g., `C:\\ffmpeg`).\n"
84
+ "3. Add `C:\\ffmpeg\\bin` to your system PATH:\n"
85
+ " - Right-click 'This PC' > 'Properties' > 'Advanced system settings' > 'Environment Variables'.\n"
86
+ " - Under 'System variables', edit 'Path' and add the new path.\n"
87
+ "4. Restart your terminal and rerun the app.")
88
+ return ""
89
+
90
+ try:
91
+ model = get_whisper_model()
92
+ # Save uploaded file to a temporary location
93
+ temp_dir = tempfile.gettempdir()
94
+ temp_file_path = os.path.join(temp_dir, "temp_audio.wav")
95
+ with open(temp_file_path, "wb") as f:
96
+ f.write(audio_file.getvalue())
97
+
98
+ # Verify file exists
99
+ if not os.path.exists(temp_file_path):
100
+ st.error(f"Temporary file not created at {temp_file_path}. Check write permissions.")
101
+ return ""
102
+
103
+ # Transcribe using Whisper
104
+ result = model.transcribe(temp_file_path)
105
+
106
+ # Clean up temporary file
107
+ if os.path.exists(temp_file_path):
108
+ os.remove(temp_file_path)
109
+ return result["text"]
110
+ except Exception as e:
111
+ st.error(f"Transcription failed: {str(e)}")
112
+ return ""
113
+
114
+ # Main App Logic
115
+ def main():
116
+ if audio_file and upload_button:
117
+ st.audio(audio_file.getvalue(), format='audio/wav')
118
+ st.caption("🎧 Uploaded Audio Playback")
119
+
120
+ with st.spinner('Analyzing audio with advanced precision...'):
121
+ transcribed_text = transcribe_audio(audio_file)
122
+ if not transcribed_text:
123
+ return
124
+
125
+ emotions_dict, top_emotion, emotion_map, sentiment = perform_emotion_detection(transcribed_text)
126
+ is_sarcastic, sarcasm_score = perform_sarcasm_detection(transcribed_text)
127
+
128
+ st.header("Transcribed Text")
129
+ st.text_area("Text", transcribed_text, height=150, disabled=True, help="The audio converted to text.")
130
+
131
+ st.header("Analysis Results")
132
+ col1, col2 = st.columns([1, 2])
133
+
134
+ with col1:
135
+ st.subheader("Sentiment")
136
+ sentiment_icon = "πŸ‘" if sentiment == "POSITIVE" else "πŸ‘Ž" if sentiment == "NEGATIVE" else "😐"
137
+ st.markdown(f"**{sentiment_icon} {sentiment.capitalize()}** (Based on {top_emotion})")
138
+ st.info("Sentiment reflects the dominant emotion’s tone.")
139
+
140
+ st.subheader("Sarcasm")
141
+ sarcasm_icon = "😏" if is_sarcastic else "😐"
142
+ sarcasm_text = "Detected" if is_sarcastic else "Not Detected"
143
+ st.markdown(f"**{sarcasm_icon} {sarcasm_text}** (Score: {sarcasm_score:.3f})")
144
+ st.info("Score indicates sarcasm confidence (0 to 1).")
145
+
146
+ with col2:
147
+ st.subheader("Emotions")
148
+ if emotions_dict:
149
+ st.markdown(f"**Dominant:** {emotion_map.get(top_emotion, '❓')} {top_emotion.capitalize()} (Score: {emotions_dict[top_emotion]:.3f})")
150
+ sorted_emotions = sorted(emotions_dict.items(), key=lambda x: x[1], reverse=True)
151
+ emotions = [e[0] for e in sorted_emotions]
152
+ scores = [e[1] for e in sorted_emotions]
153
+ fig = px.bar(x=emotions, y=scores, labels={'x': 'Emotion', 'y': 'Score'},
154
+ title="Emotion Distribution", color=emotions,
155
+ color_discrete_sequence=px.colors.qualitative.Pastel1)
156
+ fig.update_layout(yaxis_range=[0, 1], showlegend=False, title_font_size=14)
157
+ st.plotly_chart(fig, use_container_width=True)
158
+ else:
159
+ st.write("No emotions detected.")
160
+
161
+ st.info("Emotions drive sentiment here. Sarcasm is analyzed separately for accuracy.")
162
+
163
+ elif upload_button and not audio_file:
164
+ st.sidebar.error("Please upload an audio file first!")
165
+
166
+ if __name__ == "__main__":
167
+ main()