mathisescriva
Initial commit: STT + Diarization pipeline unifié
e6e14b8
import gradio as gr
import os
import tempfile
from pathlib import Path
import sys
# Importer le module de traitement
from processing import (
run_diarization,
run_transcription,
combine_diarization_transcription,
format_output
)
def process_audio_stt_diarization(
audio_file,
diarization_model
):
"""Interface Gradio pour STT + Diarization combinés."""
if audio_file is None:
return None, "❌ Veuillez uploader un fichier audio"
try:
# Gérer le chemin du fichier audio
if isinstance(audio_file, tuple):
audio_path = audio_file[1] if len(audio_file) > 1 else audio_file[0]
elif isinstance(audio_file, str):
audio_path = audio_file
elif hasattr(audio_file, 'name'):
audio_path = audio_file.name
else:
audio_path = str(audio_file)
if not os.path.exists(audio_path):
return None, f"❌ Fichier audio introuvable: {audio_path}"
# Récupérer le token HF
hf_token = os.environ.get("HF_TOKEN")
if not hf_token:
return None, "❌ Token Hugging Face non configuré (HF_TOKEN)"
# Créer un répertoire temporaire pour les résultats
with tempfile.TemporaryDirectory() as tmpdir:
# Étape 1: Diarisation
try:
diarization_segments = run_diarization(
audio_path,
hf_token,
model_name=diarization_model
)
except Exception as e:
return None, f"❌ Erreur lors de la diarisation: {str(e)}"
# Étape 2: Transcription
try:
transcription_segments = run_transcription(
audio_path,
hf_token=hf_token
)
except Exception as e:
return None, f"❌ Erreur lors de la transcription: {str(e)}"
# Étape 3: Combinaison
try:
combined = combine_diarization_transcription(
diarization_segments,
transcription_segments
)
except Exception as e:
return None, f"❌ Erreur lors de la combinaison: {str(e)}"
# Étape 4: Formatage
formatted_text = format_output(combined)
# Sauvegarder dans un fichier temporaire
output_file = os.path.join(tmpdir, "transcription.txt")
with open(output_file, 'w', encoding='utf-8') as f:
f.write(formatted_text)
# Créer un résumé
from collections import defaultdict
speaker_stats = defaultdict(lambda: {"total_duration": 0.0, "num_segments": 0, "text_length": 0})
for seg in combined:
speaker = seg["speaker"]
duration = seg["end"] - seg["start"]
speaker_stats[speaker]["total_duration"] += duration
speaker_stats[speaker]["num_segments"] += 1
speaker_stats[speaker]["text_length"] += len(seg["text"])
summary = f"""
# Résultats STT + Diarization
**Fichier:** {Path(audio_path).name}
**Modèle diarization:** {diarization_model}
**Modèle STT:** bofenghuang/whisper-large-v3-french
**Locuteurs détectés:** {len(speaker_stats)}
**Segments combinés:** {len(combined)}
## Statistiques par locuteur
"""
for speaker, stats in sorted(speaker_stats.items()):
speaker_num = int(speaker.replace("SPEAKER_", ""))
speaker_name = f"Speaker {chr(65 + speaker_num)}"
avg_duration = stats["total_duration"] / stats["num_segments"] if stats["num_segments"] > 0 else 0
summary += f"\n- **{speaker_name}**: {stats['num_segments']} segments, {stats['total_duration']:.2f}s total, {avg_duration:.2f}s moyenne/segment, {stats['text_length']} caractères"
return output_file, summary
except Exception as e:
import traceback
error_details = traceback.format_exc()
error_msg = f"""❌ **Erreur lors du traitement**
**Message:** {str(e)}
**Détails techniques:**
```
{error_details}
```
**Solutions possibles:**
- Vérifiez que le fichier audio est valide
- Assurez-vous que le token HF_TOKEN est configuré dans les secrets de la Space
- Réessayez avec un fichier audio plus court
"""
return None, error_msg
# Interface Gradio
with gr.Blocks(title="Gilbert - STT + Diarization") as demo:
gr.Markdown("""
# 🎤 Gilbert - STT + Diarization
Pipeline complet de transcription (STT) et diarisation de locuteurs.
**Fonctionnalités:**
- 🎤 Diarisation de locuteurs avec pyannote.audio
- 📝 Transcription avec Whisper Large V3 French (fine-tuné pour le français)
- 🔗 Combinaison automatique pour une sortie formatée: "Speaker A : texte"
**Instructions:**
1. Uploadez un fichier audio (WAV, MP3, M4A)
2. Configurez les paramètres de diarisation (optionnel)
3. Cliquez sur "Traiter"
4. Téléchargez la transcription avec identification des locuteurs
""")
with gr.Row():
with gr.Column():
audio_input = gr.Audio(
label="Fichier audio",
type="filepath"
)
diarization_model = gr.Dropdown(
choices=[
"pyannote/speaker-diarization-community-1",
"pyannote/speaker-diarization-3.1",
],
value="pyannote/speaker-diarization-community-1",
label="Modèle de diarisation"
)
process_btn = gr.Button("🚀 Traiter", variant="primary")
with gr.Column():
summary_output = gr.Markdown(label="Résumé")
transcription_output = gr.File(
label="Transcription (format: Speaker A : texte)",
type="filepath"
)
process_btn.click(
fn=process_audio_stt_diarization,
inputs=[audio_input, diarization_model],
outputs=[transcription_output, summary_output]
)
gr.Markdown("""
---
**Note:** Vous devez avoir un token Hugging Face configuré avec accès aux modèles pyannote et Whisper.
Configurez-le dans les secrets de la Space avec: `HF_TOKEN="votre_token"`
**Modèles utilisés:**
- **Diarization**: pyannote/speaker-diarization-community-1 (ou 3.1)
- **STT**: bofenghuang/whisper-large-v3-french (Whisper Large V3 fine-tuné pour le français)
""")
if __name__ == "__main__":
demo.launch()