gaur3009 commited on
Commit
4d65b38
·
verified ·
1 Parent(s): b840602

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -112
app.py CHANGED
@@ -1,17 +1,18 @@
1
- # app.py (Working Version without 'every' parameter)
2
  import gradio as gr
3
  import threading
4
  import queue
5
  import time
 
 
6
  from datetime import datetime
7
  from analyzer import MeetingAnalyzer
8
  from integrations import Notifier
9
  import config
 
10
 
11
  class MeetingProcessor:
12
  def __init__(self):
13
- self.recognizer = None
14
- self.stop_listening = None
15
  self.analyzer = MeetingAnalyzer()
16
  self.notifier = Notifier()
17
  self.running = False
@@ -21,8 +22,8 @@ class MeetingProcessor:
21
  self.action_items = []
22
  self.urgent_alerts = []
23
  self.transcript_queue = queue.Queue()
24
- self.ui_update_event = threading.Event()
25
- self.last_update = time.time()
26
 
27
  def start_processing(self):
28
  if self.running:
@@ -34,63 +35,68 @@ class MeetingProcessor:
34
  self.summary = ""
35
  self.action_items = []
36
  self.urgent_alerts = []
37
- self.ui_update_event.set() # Trigger UI update
 
 
 
38
 
39
  # Start processing threads
40
  threading.Thread(target=self._audio_capture_thread, daemon=True).start()
41
- threading.Thread(target=self._analysis_thread, daemon=True).start()
42
 
43
  return "Meeting processing started! 🎤"
44
 
45
  def _audio_capture_thread(self):
46
- import speech_recognition as sr
47
-
48
- self.recognizer = sr.Recognizer()
49
- self.recognizer.energy_threshold = config.ENERGY_THRESHOLD
50
- self.recognizer.dynamic_energy_threshold = config.DYNAMIC_ENERGY_THRESHOLD
51
- self.recognizer.pause_threshold = config.PAUSE_THRESHOLD
52
-
53
- with sr.Microphone() as source:
54
- print("Adjusting for ambient noise...")
55
- self.recognizer.adjust_for_ambient_noise(source, duration=1)
56
- print("Microphone ready!")
57
-
58
- def callback(recognizer, audio):
59
- try:
60
- text = recognizer.recognize_google(audio)
61
- self.transcript_queue.put(text)
62
- except sr.UnknownValueError:
63
- pass
64
- except sr.RequestError as e:
65
- print(f"Speech recognition error: {str(e)}")
66
-
67
- self.stop_listening = self.recognizer.listen_in_background(
68
- source,
69
- callback,
70
- phrase_time_limit=config.PHRASE_TIME_LIMIT
71
- )
72
-
73
- # Keep the thread running while processing
74
- while self.running:
75
- time.sleep(0.1)
76
 
77
- def _analysis_thread(self):
 
78
  while self.running:
79
  try:
80
- transcript = self.transcript_queue.get(timeout=1.0)
81
- if transcript:
82
- self.transcript_history.append(transcript)
83
- self.analyzer.process_chunk(transcript)
84
-
85
- # Check for urgent items periodically
86
- if len(self.transcript_history) % 5 == 0:
87
- urgent_items = self.analyzer.detect_urgent_action_items()
88
- if urgent_items:
89
- self.urgent_alerts.extend(urgent_items)
90
- self.notifier.send_urgent_alert(urgent_items)
91
-
92
- # Trigger UI update
93
- self.ui_update_event.set()
 
 
 
 
 
 
 
 
 
 
 
 
94
  except queue.Empty:
95
  continue
96
 
@@ -100,9 +106,6 @@ class MeetingProcessor:
100
 
101
  self.running = False
102
 
103
- if self.stop_listening:
104
- self.stop_listening(wait_for_stop=False)
105
-
106
  # Generate final analysis
107
  self.summary = self.analyzer.generate_summary()
108
  self.action_items = self.analyzer.extract_action_items()
@@ -116,9 +119,6 @@ class MeetingProcessor:
116
  recipients=config.NOTIFICATION_RECIPIENTS
117
  )
118
 
119
- # Trigger final UI update
120
- self.ui_update_event.set()
121
-
122
  return "Meeting processing stopped! Report sent. ✅"
123
 
124
  def get_current_status(self):
@@ -135,14 +135,14 @@ class MeetingProcessor:
135
  elapsed = time.time() - self.start_time
136
  mins, secs = divmod(int(elapsed), 60)
137
 
138
- # Only show last 5 transcript entries
139
- recent_transcript = "\n".join(self.transcript_history[-5:])
140
 
141
  return {
142
  "status": "Recording",
143
  "duration": f"{mins:02d}:{secs:02d}",
144
  "transcript": recent_transcript,
145
- "summary": self.summary if self.summary else "Summary will appear after meeting ends",
146
  "action_items": self.action_items,
147
  "alerts": self.urgent_alerts
148
  }
@@ -151,25 +151,26 @@ class MeetingProcessor:
151
  processor = MeetingProcessor()
152
 
153
  # Create Gradio interface
154
- with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
155
- gr.Markdown("# 🎙️ Real-Time Meeting Summarizer")
156
- gr.Markdown("Start this during any meeting to get live transcription and automatic summaries")
157
 
158
  with gr.Row():
159
  start_btn = gr.Button("Start Meeting", variant="primary")
160
  stop_btn = gr.Button("Stop Meeting", variant="stop")
161
- status_text = gr.Textbox(label="Status", interactive=False)
162
- refresh_btn = gr.Button("Refresh Now", variant="secondary")
163
 
164
  with gr.Row():
165
  with gr.Column():
166
  duration_display = gr.Textbox(label="Duration", interactive=False)
167
- transcript_box = gr.Textbox(label="Live Transcript", lines=8, interactive=False)
168
 
169
  with gr.Column():
170
- alerts_box = gr.Textbox(label="Urgent Alerts", lines=3, interactive=False)
171
- summary_box = gr.Textbox(label="Meeting Summary", lines=5, interactive=False)
172
- action_items_box = gr.Textbox(label="Action Items", lines=5, interactive=False)
 
 
173
 
174
  # Update function for components
175
  def update_components():
@@ -186,7 +187,7 @@ with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
186
  for item in current_status["alerts"]
187
  ) if current_status["alerts"] else "No urgent alerts",
188
  current_status["summary"],
189
- "Recording" if processor.running else "Stopped"
190
  ]
191
 
192
  # Button actions
@@ -194,24 +195,17 @@ with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
194
  fn=processor.start_processing,
195
  inputs=[],
196
  outputs=[status_text]
197
- ).then(
198
- update_components,
199
- inputs=[],
200
- outputs=[
201
- duration_display,
202
- transcript_box,
203
- action_items_box,
204
- alerts_box,
205
- summary_box,
206
- status_text
207
- ]
208
  )
209
 
210
  stop_btn.click(
211
  fn=processor.stop_processing,
212
  inputs=[],
213
  outputs=[status_text]
214
- ).then(
 
 
 
 
215
  update_components,
216
  inputs=[],
217
  outputs=[
@@ -224,8 +218,16 @@ with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
224
  ]
225
  )
226
 
227
- # Refresh button action
228
- refresh_btn.click(
 
 
 
 
 
 
 
 
229
  update_components,
230
  inputs=[],
231
  outputs=[
@@ -238,32 +240,5 @@ with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
238
  ]
239
  )
240
 
241
- # Auto-refresh thread
242
- def auto_refresh():
243
- while True:
244
- # Wait for update event
245
- processor.ui_update_event.wait()
246
- processor.ui_update_event.clear()
247
-
248
- # Update the UI components
249
- app.queue().put(
250
- update_components,
251
- inputs=[],
252
- outputs=[
253
- duration_display,
254
- transcript_box,
255
- action_items_box,
256
- alerts_box,
257
- summary_box,
258
- status_text
259
- ]
260
- )
261
-
262
- # Sleep briefly to avoid excessive updates
263
- time.sleep(0.5)
264
-
265
- # Start the auto-refresh thread
266
- threading.Thread(target=auto_refresh, daemon=True).start()
267
-
268
  if __name__ == "__main__":
269
  app.launch()
 
1
+ # app.py (Simplified & Robust Meeting Summarizer)
2
  import gradio as gr
3
  import threading
4
  import queue
5
  import time
6
+ import wave
7
+ import os
8
  from datetime import datetime
9
  from analyzer import MeetingAnalyzer
10
  from integrations import Notifier
11
  import config
12
+ import speech_recognition as sr
13
 
14
  class MeetingProcessor:
15
  def __init__(self):
 
 
16
  self.analyzer = MeetingAnalyzer()
17
  self.notifier = Notifier()
18
  self.running = False
 
22
  self.action_items = []
23
  self.urgent_alerts = []
24
  self.transcript_queue = queue.Queue()
25
+ self.recording_file = None
26
+ self.recognizer = sr.Recognizer()
27
 
28
  def start_processing(self):
29
  if self.running:
 
35
  self.summary = ""
36
  self.action_items = []
37
  self.urgent_alerts = []
38
+
39
+ # Create a unique filename for this recording
40
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
41
+ self.recording_file = f"meeting_{timestamp}.wav"
42
 
43
  # Start processing threads
44
  threading.Thread(target=self._audio_capture_thread, daemon=True).start()
45
+ threading.Thread(target=self._transcription_thread, daemon=True).start()
46
 
47
  return "Meeting processing started! 🎤"
48
 
49
  def _audio_capture_thread(self):
50
+ """Capture audio from microphone and save to file"""
51
+ try:
52
+ with sr.Microphone() as source:
53
+ print("Adjusting for ambient noise...")
54
+ self.recognizer.adjust_for_ambient_noise(source, duration=1)
55
+ print("Microphone ready! Recording meeting...")
56
+
57
+ # Start recording
58
+ audio = self.recognizer.listen(source, timeout=None, phrase_time_limit=300)
59
+
60
+ # Save audio to file
61
+ with open(self.recording_file, "wb") as f:
62
+ f.write(audio.get_wav_data())
63
+
64
+ # Add to queue for processing
65
+ self.transcript_queue.put(self.recording_file)
66
+
67
+ except Exception as e:
68
+ print(f"Audio capture error: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ def _transcription_thread(self):
71
+ """Transcribe audio files as they become available"""
72
  while self.running:
73
  try:
74
+ audio_file = self.transcript_queue.get(timeout=1.0)
75
+ if audio_file:
76
+ # Transcribe the audio file
77
+ with sr.AudioFile(audio_file) as source:
78
+ audio = self.recognizer.record(source)
79
+ try:
80
+ text = self.recognizer.recognize_google(audio)
81
+ self.transcript_history.append(text)
82
+ self.analyzer.process_chunk(text)
83
+
84
+ # Generate interim summary
85
+ if len(self.transcript_history) % 3 == 0:
86
+ self.summary = self.analyzer.generate_summary()
87
+ self.action_items = self.analyzer.extract_action_items()
88
+
89
+ # Check for urgent items
90
+ urgent_items = self.analyzer.detect_urgent_action_items()
91
+ if urgent_items:
92
+ self.urgent_alerts.extend(urgent_items)
93
+ self.notifier.send_urgent_alert(urgent_items)
94
+
95
+ except sr.UnknownValueError:
96
+ print("Speech recognition could not understand audio")
97
+ except sr.RequestError as e:
98
+ print(f"Speech recognition error: {str(e)}")
99
+
100
  except queue.Empty:
101
  continue
102
 
 
106
 
107
  self.running = False
108
 
 
 
 
109
  # Generate final analysis
110
  self.summary = self.analyzer.generate_summary()
111
  self.action_items = self.analyzer.extract_action_items()
 
119
  recipients=config.NOTIFICATION_RECIPIENTS
120
  )
121
 
 
 
 
122
  return "Meeting processing stopped! Report sent. ✅"
123
 
124
  def get_current_status(self):
 
135
  elapsed = time.time() - self.start_time
136
  mins, secs = divmod(int(elapsed), 60)
137
 
138
+ # Only show last 3 transcript entries
139
+ recent_transcript = "\n".join(self.transcript_history[-3:])
140
 
141
  return {
142
  "status": "Recording",
143
  "duration": f"{mins:02d}:{secs:02d}",
144
  "transcript": recent_transcript,
145
+ "summary": self.summary if self.summary else "Summary will appear during meeting",
146
  "action_items": self.action_items,
147
  "alerts": self.urgent_alerts
148
  }
 
151
  processor = MeetingProcessor()
152
 
153
  # Create Gradio interface
154
+ with gr.Blocks(title="Meeting Notes Generator", theme="soft") as app:
155
+ gr.Markdown("# 📝 Meeting Notes Generator")
156
+ gr.Markdown("Start this during any meeting to automatically capture notes and action items")
157
 
158
  with gr.Row():
159
  start_btn = gr.Button("Start Meeting", variant="primary")
160
  stop_btn = gr.Button("Stop Meeting", variant="stop")
161
+ status_text = gr.Textbox(label="Status", interactive=False, value="Ready to start meeting")
 
162
 
163
  with gr.Row():
164
  with gr.Column():
165
  duration_display = gr.Textbox(label="Duration", interactive=False)
166
+ transcript_box = gr.Textbox(label="Live Transcript", lines=6, interactive=False)
167
 
168
  with gr.Column():
169
+ summary_box = gr.Textbox(label="Meeting Summary", lines=6, interactive=False)
170
+
171
+ with gr.Row():
172
+ action_items_box = gr.Textbox(label="Action Items", lines=4, interactive=False)
173
+ alerts_box = gr.Textbox(label="Urgent Alerts", lines=4, interactive=False)
174
 
175
  # Update function for components
176
  def update_components():
 
187
  for item in current_status["alerts"]
188
  ) if current_status["alerts"] else "No urgent alerts",
189
  current_status["summary"],
190
+ current_status["status"]
191
  ]
192
 
193
  # Button actions
 
195
  fn=processor.start_processing,
196
  inputs=[],
197
  outputs=[status_text]
 
 
 
 
 
 
 
 
 
 
 
198
  )
199
 
200
  stop_btn.click(
201
  fn=processor.stop_processing,
202
  inputs=[],
203
  outputs=[status_text]
204
+ )
205
+
206
+ # Manual refresh button
207
+ refresh_btn = gr.Button("Refresh View", variant="secondary")
208
+ refresh_btn.click(
209
  update_components,
210
  inputs=[],
211
  outputs=[
 
218
  ]
219
  )
220
 
221
+ # Instructions
222
+ gr.Markdown("### How to use:")
223
+ gr.Markdown("1. Click **Start Meeting** when your meeting begins")
224
+ gr.Markdown("2. Continue with your meeting as normal")
225
+ gr.Markdown("3. Click **Stop Meeting** when finished")
226
+ gr.Markdown("4. View your meeting summary and action items below")
227
+ gr.Markdown("5. Click **Refresh View** to update the display")
228
+
229
+ # Initialize with current status
230
+ app.load(
231
  update_components,
232
  inputs=[],
233
  outputs=[
 
240
  ]
241
  )
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  if __name__ == "__main__":
244
  app.launch()