Adjoumani's picture
Update app.py
168bda2 verified
import streamlit as st
from audio_recorder_streamlit import audio_recorder
import os
import tempfile
from typing import List
from pydub import AudioSegment
from groq import Groq
from langchain.chains import LLMChain
from langchain_groq import ChatGroq
from langchain.prompts import PromptTemplate
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
import re
from dotenv import load_dotenv
load_dotenv()
SENDER_EMAIL = os.environ.get('SENDER_EMAIL')
SENDER_PASSWORD = os.environ.get('SENDER_PASSWORD')
class PDFGenerator:
@staticmethod
def create_pdf(content: str, filename: str) -> str:
doc = SimpleDocTemplate(filename, pagesize=letter)
styles = getSampleStyleSheet()
custom_style = ParagraphStyle(
'CustomStyle',
parent=styles['Normal'],
spaceBefore=12,
spaceAfter=12,
fontSize=12,
leading=14,
)
story = []
# Ajouter le titre
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Heading1'],
fontSize=16,
spaceAfter=30,
)
story.append(Paragraph("Résumé Audio", title_style))
# Ajouter la date
date_str = datetime.now().strftime("%d/%m/%Y %H:%M")
story.append(Paragraph(f"Date: {date_str}", custom_style))
story.append(Spacer(1, 20))
# Convertir le contenu en paragraphes
for line in content.split('\n'):
if line.strip():
if line.startswith('#'):
# C'est un titre
story.append(Paragraph(line.strip('# '), styles['Heading2']))
else:
story.append(Paragraph(line, custom_style))
doc.build(story)
return filename
class EmailSender:
def __init__(self, sender_email: str, sender_password: str):
self.sender_email = sender_email
self.sender_password = sender_password
def send_email(self, recipient_email: str, subject: str, body: str, pdf_path: str) -> bool:
try:
msg = MIMEMultipart()
msg['From'] = self.sender_email
msg['To'] = recipient_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
with open(pdf_path, 'rb') as f:
pdf_attachment = MIMEApplication(f.read(), _subtype='pdf')
pdf_attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(pdf_path))
msg.attach(pdf_attachment)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(self.sender_email, self.sender_password)
server.send_message(msg)
server.quit()
return True
except Exception as e:
st.error(f"Erreur d'envoi d'email: {str(e)}")
return False
# ... [Garder la classe AudioProcessor inchangée] ...
class AudioProcessor:
def __init__(self, chunk_length_ms: int = 60000):
self.chunk_length_ms = chunk_length_ms
self.groq_client = Groq(
#api_key=""
)
self.llm = ChatGroq(
model="mixtral-8x7b-32768",
temperature=0.7,
#api_key=""
)
def chunk_audio(self, file_path: str) -> List[AudioSegment]:
audio = AudioSegment.from_file(file_path)
chunks = [
audio[i:i + self.chunk_length_ms]
for i in range(0, len(audio), self.chunk_length_ms)
]
return chunks
def transcribe_chunk(self, audio_chunk: AudioSegment) -> str:
with tempfile.NamedTemporaryFile(suffix='.mp3', delete=True) as temp_file:
audio_chunk.export(temp_file.name, format="mp3")
with open(temp_file.name, "rb") as audio_file:
response = self.groq_client.audio.transcriptions.create(
file=audio_file,
model="whisper-large-v3-turbo",
language="fr"
)
return response.text
def generate_summary(self, transcription: str) -> str:
prompt_template = """
Vous êtes un assistant expert spécialisé dans le résumé et l'analyse d'enregistrements audio en langue française.
Voici la transcription à analyser:
{transcript}
Veuillez fournir:
1. Un résumé concis (3-4 phrases)
2. Les points clés (maximum 5 points)
3. Les actions recommandées (si pertinent)
4. Une conclusion brève
Format souhaité:
# Résumé
[votre résumé]
# Points Clés
• [point 1]
• [point 2]
...
# Actions Recommandées
1. [action 1]
2. [action 2]
...
# Conclusion
[votre conclusion]
"""
chain = LLMChain(
llm=self.llm,
prompt=PromptTemplate(
template=prompt_template,
input_variables=["transcript"]
)
)
return chain.run(transcript=transcription)
def save_uploaded_file(uploaded_file):
with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(uploaded_file.name)[1]) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
return tmp_file.name
def is_valid_email(email: str) -> bool:
pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
return re.match(pattern, email) is not None
def main():
st.set_page_config(page_title="Audio Summarizer", page_icon="🎙️")
# Configuration email dans les secrets de Streamlit
#SENDER_EMAIL = ""
#SENDER_PASSWORD = ""
email_sender = EmailSender(SENDER_EMAIL, SENDER_PASSWORD)
st.title("🎙️ Audio Summarizer")
# Initialisation des sessions states
if 'audio_processor' not in st.session_state:
st.session_state.audio_processor = AudioProcessor()
# Interface utilisateur
st.markdown("### 📤 Chargez votre fichier audio")
uploaded_file = st.file_uploader("", type=['mp3', 'wav', 'm4a', 'ogg'])
# Zone d'enregistrement audio
st.markdown("### 🎤 Ou enregistrez directement")
audio_bytes = audio_recorder()
if audio_bytes:
st.audio(audio_bytes, format="audio/wav")
if uploaded_file or audio_bytes:
with st.spinner("Traitement en cours..."):
try:
if uploaded_file:
file_path = save_uploaded_file(uploaded_file)
else:
# Sauvegarder l'enregistrement audio
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
file_path = f"recording_{timestamp}.wav"
with open(file_path, 'wb') as f:
f.write(audio_bytes)
# Traitement de l'audio
chunks = st.session_state.audio_processor.chunk_audio(file_path)
# Transcription
with st.expander("Transcription", expanded=False):
transcriptions = []
progress_bar = st.progress(0)
for i, chunk in enumerate(chunks):
transcription = st.session_state.audio_processor.transcribe_chunk(chunk)
transcriptions.append(transcription)
progress_bar.progress((i + 1) / len(chunks))
full_transcription = " ".join(transcriptions)
st.text_area("Texte transcrit:", value=full_transcription, height=200)
# Génération du résumé
summary = st.session_state.audio_processor.generate_summary(full_transcription)
st.markdown("### 📝 Résumé et Analyse")
st.markdown(summary)
# Création du PDF
pdf_filename = f"resume_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
pdf_path = PDFGenerator.create_pdf(summary, pdf_filename)
# Options d'exportation
with open(pdf_path, "rb") as pdf_file:
pdf_bytes = pdf_file.read()
st.download_button(
label="📥 Télécharger le résumé (PDF)",
data=pdf_bytes,
file_name=pdf_filename,
mime="application/pdf"
)
# Section d'envoi par email
st.markdown("### 📧 Recevoir le résumé par email")
recipient_email = st.text_input("Entrez votre adresse email:")
if st.button("Envoyer par email"):
if not is_valid_email(recipient_email):
st.error("Veuillez entrer une adresse email valide.")
else:
with st.spinner("Envoi de l'email en cours..."):
email_body = "Veuillez trouver ci-joint le résumé de votre audio."
if email_sender.send_email(
recipient_email,
"Résumé de votre enregistrement audio",
email_body,
pdf_path
):
st.success("Email envoyé avec succès!")
else:
st.error("Échec de l'envoi de l'email.")
except Exception as e:
st.error(f"Une erreur est survenue: {str(e)}")
finally:
# Nettoyage des fichiers temporaires
if 'file_path' in locals():
os.unlink(file_path)
if 'pdf_path' in locals():
os.unlink(pdf_path)
if __name__ == "__main__":
main()