Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import os | |
| import tempfile | |
| from pathlib import Path | |
| import sys | |
| # Importer le script de diarisation (dans le même répertoire) | |
| from diarization_pyannote_demo import run_pyannote_diarization, write_rttm, write_json | |
| def diarize_audio(audio_file, model_name, num_speakers, min_speakers, max_speakers, use_exclusive): | |
| """Interface Gradio pour la diarisation pyannote.""" | |
| if audio_file is None: | |
| return None, None, "❌ Veuillez uploader un fichier audio" | |
| try: | |
| # Gérer le chemin du fichier audio (Gradio peut retourner un tuple ou un string) | |
| if isinstance(audio_file, tuple): | |
| # Gradio Audio avec type="filepath" retourne (sample_rate, filepath) | |
| audio_path = audio_file[1] if len(audio_file) > 1 else audio_file[0] | |
| elif isinstance(audio_file, str): | |
| # C'est déjà un chemin de fichier | |
| audio_path = audio_file | |
| elif hasattr(audio_file, 'name'): | |
| # Objet avec attribut name | |
| audio_path = audio_file.name | |
| else: | |
| # Fallback | |
| audio_path = str(audio_file) | |
| if not os.path.exists(audio_path): | |
| return None, None, f"❌ Fichier audio introuvable: {audio_path}" | |
| # Créer un répertoire temporaire pour les résultats | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| # Exécuter la diarisation | |
| result = run_pyannote_diarization( | |
| audio_path, | |
| output_dir=tmpdir, | |
| model_name=model_name, | |
| num_speakers=num_speakers if num_speakers > 0 else None, | |
| min_speakers=min_speakers if min_speakers > 0 else None, | |
| max_speakers=max_speakers if max_speakers > 0 else None, | |
| use_exclusive=use_exclusive, | |
| show_progress=False | |
| ) | |
| # Générer les fichiers de sortie | |
| audio_name = Path(audio_path).stem | |
| rttm_path = os.path.join(tmpdir, f"{audio_name}.rttm") | |
| json_path = os.path.join(tmpdir, f"{audio_name}.json") | |
| write_rttm(result["segments"], rttm_path, audio_name) | |
| write_json(result["segments"], json_path) | |
| # Créer un résumé | |
| summary = f""" | |
| # Résultats de diarisation | |
| **Fichier:** {Path(audio_path).name} | |
| **Modèle:** {model_name} | |
| **Locuteurs détectés:** {result['num_speakers']} | |
| **Segments:** {len(result['segments'])} | |
| **Durée totale:** {result.get('duration', 0):.2f} secondes | |
| ## Statistiques par locuteur | |
| """ | |
| from collections import defaultdict | |
| speaker_stats = defaultdict(lambda: {"total_duration": 0.0, "num_segments": 0}) | |
| for seg in result["segments"]: | |
| speaker = seg["speaker"] | |
| duration = seg["end"] - seg["start"] | |
| speaker_stats[speaker]["total_duration"] += duration | |
| speaker_stats[speaker]["num_segments"] += 1 | |
| for speaker, stats in sorted(speaker_stats.items()): | |
| avg_duration = stats["total_duration"] / stats["num_segments"] if stats["num_segments"] > 0 else 0 | |
| summary += f"\n- **{speaker}**: {stats['num_segments']} segments, {stats['total_duration']:.2f}s total, {avg_duration:.2f}s moyenne/segment" | |
| # Retourner les fichiers (Gradio gère automatiquement les fichiers temporaires) | |
| return rttm_path, json_path, summary | |
| except Exception as e: | |
| import traceback | |
| error_details = traceback.format_exc() | |
| error_msg = f"""❌ **Erreur lors de la diarisation** | |
| **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, None, error_msg | |
| # Interface Gradio | |
| with gr.Blocks(title="Gilbert - Diarisation pyannote") as demo: | |
| gr.Markdown(""" | |
| # 🎤 Gilbert - Diarisation pyannote | |
| Interface pour la diarisation de locuteurs avec pyannote.audio | |
| **Instructions:** | |
| 1. Uploadez un fichier audio (WAV, MP3, M4A) | |
| 2. Configurez les paramètres (optionnel) | |
| 3. Cliquez sur "Diariser" | |
| 4. Téléchargez les résultats (RTTM et JSON) | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| audio_input = gr.Audio( | |
| label="Fichier audio", | |
| type="filepath" | |
| ) | |
| model_name = gr.Dropdown( | |
| choices=[ | |
| "pyannote/speaker-diarization-3.1", | |
| "pyannote/speaker-diarization-community-1", | |
| ], | |
| value="pyannote/speaker-diarization-3.1", | |
| label="Modèle pyannote" | |
| ) | |
| with gr.Row(): | |
| num_speakers = gr.Number( | |
| label="Nombre exact de locuteurs", | |
| value=0, | |
| minimum=0, | |
| info="0 = auto-détection" | |
| ) | |
| min_speakers = gr.Number( | |
| label="Min locuteurs", | |
| value=0, | |
| minimum=0, | |
| info="0 = pas de limite" | |
| ) | |
| max_speakers = gr.Number( | |
| label="Max locuteurs", | |
| value=0, | |
| minimum=0, | |
| info="0 = pas de limite" | |
| ) | |
| use_exclusive = gr.Checkbox( | |
| label="Exclusive speaker diarization", | |
| value=False, | |
| info="Simplifie la réconciliation avec transcription" | |
| ) | |
| diarize_btn = gr.Button("🎯 Diariser", variant="primary") | |
| with gr.Column(): | |
| summary_output = gr.Markdown(label="Résumé") | |
| rttm_output = gr.File(label="Fichier RTTM", type="filepath") | |
| json_output = gr.File(label="Fichier JSON", type="filepath") | |
| diarize_btn.click( | |
| fn=diarize_audio, | |
| inputs=[audio_input, model_name, num_speakers, min_speakers, max_speakers, use_exclusive], | |
| outputs=[rttm_output, json_output, summary_output] | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| **Note:** Vous devez avoir un token Hugging Face configuré avec accès aux modèles pyannote. | |
| Configurez-le avec: `export HF_TOKEN="votre_token"` | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() | |