import 'package:flutter_tts/flutter_tts.dart'; import 'package:em2rp/utils/debug_log.dart'; /// Service de synthèse vocale pour lire des textes à haute voix class TextToSpeechService { static final FlutterTts _tts = FlutterTts(); static bool _isInitialized = false; /// Initialiser le service TTS static Future initialize() async { if (_isInitialized) return; try { await _tts.setLanguage('fr-FR'); await _tts.setSpeechRate(0.7); // Vitesse normale await _tts.setVolume(1.0); await _tts.setPitch(0.7); // Pitch plus bas pour une voix masculine // Tenter de sélectionner une voix masculine si disponible try { final voices = await _tts.getVoices; if (voices != null && voices is List) { // Chercher une voix française masculine final maleVoice = voices.firstWhere( (voice) { final voiceMap = voice as Map; final name = voiceMap['name']?.toString().toLowerCase() ?? ''; final locale = voiceMap['locale']?.toString().toLowerCase() ?? ''; // Rechercher des voix françaises masculines return locale.startsWith('fr') && (name.contains('male') || name.contains('homme') || name.contains('thomas') || name.contains('paul')); }, orElse: () => null, ); if (maleVoice != null) { final voiceMap = maleVoice as Map; await _tts.setVoice({ 'name': voiceMap['name'], 'locale': voiceMap['locale'], }); DebugLog.info('[TextToSpeechService] Voix masculine sélectionnée: ${voiceMap['name']}'); } } } catch (e) { DebugLog.info('[TextToSpeechService] Impossible de sélectionner une voix spécifique, utilisation de la voix par défaut'); } _isInitialized = true; DebugLog.info('[TextToSpeechService] Service initialisé avec voix masculine'); } catch (e) { DebugLog.error('[TextToSpeechService] Erreur lors de l\'initialisation', e); } } /// Lire un texte à haute voix static Future speak(String text) async { if (!_isInitialized) { await initialize(); } try { // Arrêter toute lecture en cours await _tts.stop(); // Lire le nouveau texte await _tts.speak(text); DebugLog.info('[TextToSpeechService] Lecture: $text'); } catch (e) { DebugLog.error('[TextToSpeechService] Erreur lors de la lecture', e); } } /// Arrêter la lecture en cours static Future stop() async { try { await _tts.stop(); } catch (e) { DebugLog.error('[TextToSpeechService] Erreur lors de l\'arrêt', e); } } /// Vérifier si le service est en train de lire static Future isSpeaking() async { try { // FlutterTts ne fournit pas directement cette info, on retourne false par défaut return false; } catch (e) { return false; } } /// Nettoyer les ressources static Future dispose() async { try { await _tts.stop(); } catch (e) { DebugLog.error('[TextToSpeechService] Erreur lors du nettoyage', e); } } }