import 'dart:io'; import 'package:loopin/IM/im_core.dart'; import 'package:path_provider/path_provider.dart'; import 'package:record/record.dart'; class VoiceService { static final VoiceService _instance = VoiceService._internal(); factory VoiceService() => _instance; VoiceService._internal(); final AudioRecorder _recorder = AudioRecorder(); String? _voiceFilePath; DateTime? _startTime; /// 开始录音 Future startRecording() async { if (await _recorder.hasPermission()) { // final dir = await getTemporaryDirectory(); // 临时目录 final dir = await getApplicationDocumentsDirectory(); // 临时目录在ios不行 final filePath = '${dir.path}/${DateTime.now().millisecondsSinceEpoch}.m4a'; _voiceFilePath = filePath; _startTime = DateTime.now(); await _recorder.start( const RecordConfig( encoder: AudioEncoder.aacLc, bitRate: 128000, sampleRate: 44100, ), path: filePath, ); logger.i('开始录音,文件路径: $filePath'); return true; } else { logger.e("没有录音权限"); return false; } } /// 停止录音并返回文件路径 Future?> stopRecording() async { await _recorder.stop(); if (_voiceFilePath != null && File(_voiceFilePath!).existsSync() && _startTime != null) { final duration = DateTime.now().difference(_startTime!); final durationSeconds = duration.inSeconds; if (durationSeconds < 1 || durationSeconds > 60) { logger.w('录音时长不在允许范围(1-60秒),删除文件: $_voiceFilePath,时长: $durationSeconds 秒'); try { await File(_voiceFilePath!).delete(); } catch (e) { logger.e('删除录音文件失败: $e'); } return null; } logger.i('录音完成: $_voiceFilePath,时长: ${duration.inSeconds}秒'); return { 'path': _voiceFilePath, 'duration': duration.inMilliseconds, }; } logger.e("没有录到音频文件"); return null; } /// 取消录音(删除文件) Future cancelRecording() async { await _recorder.stop(); if (_voiceFilePath != null) { final file = File(_voiceFilePath!); if (await file.exists()) { await file.delete(); logger.i('录音已取消并删除'); } } _voiceFilePath = null; } }