MemoirAI / app.py
gaur3009's picture
Update app.py
23c62ec verified
raw
history blame
8.63 kB
# app.py (Final Working Version)
import gradio as gr
import threading
import queue
import time
from datetime import datetime
from analyzer import MeetingAnalyzer
from integrations import Notifier
import config
class MeetingProcessor:
def __init__(self):
self.recognizer = None
self.stop_listening = None
self.analyzer = MeetingAnalyzer()
self.notifier = Notifier()
self.running = False
self.start_time = None
self.transcript_history = []
self.summary = ""
self.action_items = []
self.urgent_alerts = []
self.transcript_queue = queue.Queue()
self.last_update = time.time()
def start_processing(self):
if self.running:
return "Already running!"
self.running = True
self.start_time = time.time()
self.transcript_history = []
self.summary = ""
self.action_items = []
self.urgent_alerts = []
# Start processing threads
threading.Thread(target=self._audio_capture_thread, daemon=True).start()
threading.Thread(target=self._analysis_thread, daemon=True).start()
return "Meeting processing started! 🎤"
def _audio_capture_thread(self):
import speech_recognition as sr
self.recognizer = sr.Recognizer()
self.recognizer.energy_threshold = config.ENERGY_THRESHOLD
self.recognizer.dynamic_energy_threshold = config.DYNAMIC_ENERGY_THRESHOLD
self.recognizer.pause_threshold = config.PAUSE_THRESHOLD
with sr.Microphone() as source:
print("Adjusting for ambient noise...")
self.recognizer.adjust_for_ambient_noise(source, duration=1)
print("Microphone ready!")
def callback(recognizer, audio):
try:
text = recognizer.recognize_google(audio)
self.transcript_queue.put(text)
except sr.UnknownValueError:
pass
except sr.RequestError as e:
print(f"Speech recognition error: {str(e)}")
self.stop_listening = self.recognizer.listen_in_background(
source,
callback,
phrase_time_limit=config.PHRASE_TIME_LIMIT
)
# Keep the thread running while processing
while self.running:
time.sleep(0.1)
def _analysis_thread(self):
while self.running:
try:
transcript = self.transcript_queue.get(timeout=1.0)
if transcript:
self.transcript_history.append(transcript)
self.analyzer.process_chunk(transcript)
# Check for urgent items periodically
if len(self.transcript_history) % 5 == 0:
urgent_items = self.analyzer.detect_urgent_action_items()
if urgent_items:
self.urgent_alerts.extend(urgent_items)
self.notifier.send_urgent_alert(urgent_items)
# Update timestamp for UI
self.last_update = time.time()
except queue.Empty:
continue
def stop_processing(self):
if not self.running:
return "Not running!"
self.running = False
if self.stop_listening:
self.stop_listening(wait_for_stop=False)
# Generate final analysis
self.summary = self.analyzer.generate_summary()
self.action_items = self.analyzer.extract_action_items()
# Send final report
self.notifier.send_comprehensive_report(
summary=self.summary,
action_items=self.action_items,
decisions=self.analyzer.extract_decisions(),
transcript="\n".join(self.transcript_history),
recipients=config.NOTIFICATION_RECIPIENTS
)
return "Meeting processing stopped! Report sent. ✅"
def get_current_status(self):
if not self.running:
return {
"status": "Stopped",
"duration": "00:00",
"transcript": "",
"summary": self.summary,
"action_items": self.action_items,
"alerts": self.urgent_alerts
}
elapsed = time.time() - self.start_time
mins, secs = divmod(int(elapsed), 60)
# Only show last 5 transcript entries
recent_transcript = "\n".join(self.transcript_history[-5:])
return {
"status": "Recording",
"duration": f"{mins:02d}:{secs:02d}",
"transcript": recent_transcript,
"summary": self.summary if self.summary else "Summary will appear after meeting ends",
"action_items": self.action_items,
"alerts": self.urgent_alerts
}
# Initialize processor
processor = MeetingProcessor()
# Create Gradio interface
with gr.Blocks(title="Real-Time Meeting Summarizer", theme="soft") as app:
gr.Markdown("# 🎙️ Real-Time Meeting Summarizer")
gr.Markdown("Start this during any meeting to get live transcription and automatic summaries")
with gr.Row():
start_btn = gr.Button("Start Meeting", variant="primary")
stop_btn = gr.Button("Stop Meeting", variant="stop")
status_text = gr.Textbox(label="Status", interactive=False)
refresh_btn = gr.Button("Refresh", variant="secondary")
last_update = gr.State(value=0) # Track last update time
with gr.Row():
with gr.Column():
duration_display = gr.Textbox(label="Duration", interactive=False)
transcript_box = gr.Textbox(label="Live Transcript", lines=8, interactive=False)
with gr.Column():
alerts_box = gr.Textbox(label="Urgent Alerts", lines=3, interactive=False)
summary_box = gr.Textbox(label="Meeting Summary", lines=5, interactive=False)
action_items_box = gr.Textbox(label="Action Items", lines=5, interactive=False)
# Update function for components
def update_components():
current_status = processor.get_current_status()
return [
current_status["duration"],
current_status["transcript"],
"\n".join(
f"• {item['task']} (Owner: {item['owner']}, Deadline: {item['deadline']})"
for item in current_status["action_items"]
),
"\n".join(
f"🚨 {item['task']} (Owner: {item['owner']}, Deadline: {item['deadline']})"
for item in current_status["alerts"]
) if current_status["alerts"] else "No urgent alerts",
current_status["summary"],
time.time() # Update timestamp
]
# Button actions
start_btn.click(
fn=processor.start_processing,
inputs=[],
outputs=[status_text]
).then(
fn=lambda: 0,
inputs=[],
outputs=[last_update]
)
stop_btn.click(
fn=processor.stop_processing,
inputs=[],
outputs=[status_text]
).then(
update_components,
inputs=[],
outputs=[
duration_display,
transcript_box,
action_items_box,
alerts_box,
summary_box,
last_update
]
)
# Refresh button action
refresh_btn.click(
update_components,
inputs=[],
outputs=[
duration_display,
transcript_box,
action_items_box,
alerts_box,
summary_box,
last_update
]
)
# Auto-refresh when meeting is running
def check_for_updates(last_update_time):
if processor.running and processor.last_update > last_update_time:
return update_components() + [processor.last_update]
return [gr.update()] * 5 + [last_update_time]
# Set up periodic auto-refresh
app.load(
fn=check_for_updates,
inputs=[last_update],
outputs=[
duration_display,
transcript_box,
action_items_box,
alerts_box,
summary_box,
last_update
],
every=1
)
if __name__ == "__main__":
app.launch()