import 'dart:async'; import 'dart:io'; import 'dart:typed_data'; import 'package:audioplayers/audioplayers.dart'; import 'package:path_provider/path_provider.dart'; class AudioTool { AudioTool._(); static final AudioTool share = AudioTool._(); factory AudioTool() => share; ///所有的音频数据 List _audioChunks = []; ///分断合并的数组,达到一定数量后合并去播放 List _playTemps = []; ///存放合并后的音频数组用于播放,播放完一个删除一个直到播放全部 // List _playBuff = []; ///是否已经播放了,play只被主动调用一次,然后根据_playBuff的数组递归 bool isPlaying = false; final player = AudioPlayer(); void dispose() async { await player.stop(); await player.dispose(); } void addAudioChunk( {required AudioModel model, required Function(String) onPath, required Function() onPlaying, required Function() onPlayEnd}) async { if (model.status == 0 || model.status == 1) { _audioChunks.add(model.data); _playTemps.add(model.data); } else if (model.status == 2) { _audioChunks.add(model.data); _playTemps.add(model.data); final path = await mergeAudioChunks( sid: model.sid, chunks: _playTemps, onPlaying: onPlaying, onPlayEnd: onPlayEnd); onPath(path); } } Future mergeAudioChunks( {required String sid, required List chunks, required Function() onPlaying, required Function() onPlayEnd}) async { // 计算总长度 int totalLength = chunks.fold(0, (sum, chunk) => sum + chunk.length); // 创建合并后的 Uint8List final mergedData = Uint8List(totalLength); int offset = 0; for (var chunk in chunks) { mergedData.setRange(offset, offset + chunk.length, chunk); offset += chunk.length; } ///保存到文件或上传 // Logger().f('------isFinal--------保存文件'); _audioChunks = []; _playTemps = []; // _playBuff.add(mergedData); // if (!isPlaying) { // isPlaying = true; // play(bytes: mergedData, onPlaying: onPlaying, onPlayEnd: onPlayEnd); // } final dir = await getApplicationSupportDirectory(); final path = dir.path + '/$sid.mp3'; File file = File(path); await file.writeAsBytes(mergedData); return path; } void play( {required Uint8List bytes, required Function() onPlaying, required Function() onPlayEnd}) async { // Logger().f('------_playBuff--------${_playBuff.length}'); // if (_playBuff.isNotEmpty) { await player.onPlayerStateChanged.listen((sta) async { if (sta == PlayerState.completed) { isPlaying = false; // if (_playBuff.isNotEmpty) { // _playBuff.removeAt(0); // } onPlayEnd(); } }); final source = BytesSource(bytes, mimeType: 'audio/mp3'); onPlaying(); await player.play(source); // } else { // isPlaying = false; // } } static Uint8List mergeAudio({required List chunks}) { // 计算总长度 int totalLength = chunks.fold(0, (sum, chunk) => sum + chunk.length); // 创建合并后的 Uint8List final mergedData = Uint8List(totalLength); int offset = 0; for (var chunk in chunks) { mergedData.setRange(offset, offset + chunk.length, chunk); offset += chunk.length; } return mergedData; } } class AudioModel { int status; String sid; Uint8List data; AudioModel({required this.status, required this.sid, required this.data}); }