import 'package:audioplayers/audioplayers.dart'; import 'package:get/get.dart'; /// 语音播放管理器,单例模式,统一管理语音播放 class VoicePlayerManager extends GetxController { static VoicePlayerManager? _instance; static VoicePlayerManager get instance { _instance ??= Get.put(VoicePlayerManager()); return _instance!; } final AudioPlayer _audioPlayer = AudioPlayer(); String? _currentPlayingId; final Rx currentPlayingId = Rx(null); final Rx playerState = Rx(PlayerState.stopped); VoicePlayerManager() { // 监听播放状态变化 _audioPlayer.onPlayerStateChanged.listen((state) { playerState.value = state; if (state == PlayerState.completed) { // 播放完成,重置状态 _currentPlayingId = null; currentPlayingId.value = null; } }); } /// 播放音频 /// [audioId] 音频的唯一标识(通常是消息ID) /// [filePath] 音频文件路径 Future play(String audioId, String filePath) async { try { print('🎵 [VoicePlayerManager] 准备播放音频: audioId=$audioId, filePath=$filePath'); // 如果是同一个音频,则暂停/恢复 if (_currentPlayingId == audioId) { print('⏯️ [VoicePlayerManager] 切换播放/暂停状态'); try { if (playerState.value == PlayerState.playing) { await _audioPlayer.pause(); } else { await _audioPlayer.resume(); } } catch (e) { print('⚠️ [VoicePlayerManager] 暂停/恢复失败,尝试重新播放: $e'); // 如果暂停/恢复失败,继续执行播放新音频的逻辑 } // 如果成功暂停/恢复,直接返回 if (_currentPlayingId == audioId && (playerState.value == PlayerState.playing || playerState.value == PlayerState.paused)) { return; } } // 如果正在播放其他音频,先停止 if (_currentPlayingId != null && _currentPlayingId != audioId) { print('🛑 [VoicePlayerManager] 停止当前播放的音频: $_currentPlayingId'); try { // 只在播放器状态不是 stopped 时才调用 stop if (playerState.value != PlayerState.stopped) { await _audioPlayer.stop(); } } catch (e) { print('⚠️ [VoicePlayerManager] 停止播放器时出错(可忽略): $e'); } // 重置当前播放ID _currentPlayingId = null; currentPlayingId.value = null; // 等待一小段时间确保停止完成 await Future.delayed(Duration(milliseconds: 200)); } // 播放新音频前,如果播放器正在播放或暂停,先停止 print('🔄 [VoicePlayerManager] 准备播放新音频,当前状态: ${playerState.value}'); if (playerState.value == PlayerState.playing || playerState.value == PlayerState.paused) { try { await _audioPlayer.stop(); await Future.delayed(Duration(milliseconds: 150)); } catch (e) { // 如果 stop 失败,可能是播放器还没有初始化,继续尝试播放 print('⚠️ [VoicePlayerManager] 停止播放器时出错(可忽略): $e'); } } // 设置当前播放的音频ID _currentPlayingId = audioId; currentPlayingId.value = audioId; // 根据路径类型选择不同的播放源 if (filePath.startsWith('http://') || filePath.startsWith('https://')) { print('🌐 [VoicePlayerManager] 使用网络URL播放: $filePath'); await _audioPlayer.play(UrlSource(filePath)); } else { print('📁 [VoicePlayerManager] 使用本地文件播放: $filePath'); await _audioPlayer.play(DeviceFileSource(filePath)); } print('✅ [VoicePlayerManager] 音频播放请求已发送'); } catch (e, stackTrace) { print('❌ [VoicePlayerManager] 播放音频失败: $e'); print('📚 [VoicePlayerManager] 堆栈跟踪: $stackTrace'); // 重置状态 _currentPlayingId = null; currentPlayingId.value = null; // 重新抛出异常,让调用者知道播放失败 rethrow; } } /// 停止播放 Future stop() async { try { // 只在播放器状态不是 stopped 时才调用 stop if (playerState.value != PlayerState.stopped) { await _audioPlayer.stop(); } _currentPlayingId = null; currentPlayingId.value = null; } catch (e) { print('⚠️ [VoicePlayerManager] 停止播放失败(可忽略): $e'); // 即使停止失败,也重置状态 _currentPlayingId = null; currentPlayingId.value = null; } } /// 暂停播放 Future pause() async { try { await _audioPlayer.pause(); } catch (e) { print('暂停播放失败: $e'); } } /// 检查指定音频是否正在播放 bool isPlaying(String audioId) { return _currentPlayingId == audioId && playerState.value == PlayerState.playing; } /// 检查指定音频是否已加载 bool isLoaded(String audioId) { return _currentPlayingId == audioId; } @override void onClose() { _audioPlayer.dispose(); super.onClose(); } }