由于我的音频文件数据是接口返回的uint8List(addStreamChunk方法),需要拼接,但要求立即播放,所以我设置了一个缓冲区,边接收边播放。但是现在有新的音频片段时,只能在_safePlay方法中重新调用_audioPlayer.resume()才能播放。否则,只添加_audioPlayer.setSourceBytes(audioData)是不会播放新添加的语音片段的,会导致播放卡顿。那么该如何修改才能保证每次添加新的音频片段时不用调用resume呢?
import 'dart:async';
import 'dart:typed_data';
import 'package:audioplayers/audioplayers.dart' as audio;
import 'package:synchronized/synchronized.dart';
class AudioManager {
static AudioManager? _instance;
static final Lock _instanceLock = Lock();
factory AudioManager() {
return _instance ??= AudioManager._internal();
}
static Future<AudioManager> get instance async {
return await _instanceLock.synchronized(() async {
_instance ??= AudioManager._internal();
return _instance!;
});
}
AudioManager._internal() {
_init();
}
final audio.AudioPlayer _audioPlayer = audio.AudioPlayer();
final Lock _playLock = Lock();
final List<int> _audioBuffer = [];
bool _isStreamMode = false;
bool _isPlaying = false;
bool _isPaused = false;
Completer<void>? _streamCompleter;
Timer? _streamCompletionTimer;
bool _streamFinished = false; // 标记流是否已结束
bool _hasStartedPlaying = false; // 标记是否已开始播放,用于快速启动
static const int _minBufferSize = 16384; // 16KB - 减少初始缓冲减少卡顿
static const int _maxBufferSize = 32768; // 32KB - 减少最大缓冲提高响应性
static const Duration _streamCompletionDelay = Duration(milliseconds: 200); // 进一步优化延迟
static const Duration _playerResetDelay = Duration(milliseconds: 30); // 进一步减少重置延迟
static const Duration _stateStabilizationDelay = Duration(milliseconds: 20); // 减少状态稳定延迟
// ========== 公共属性 ==========
bool get isStreamMode => _isStreamMode;
bool get isPlaying => _isPlaying;
bool get isPaused => _isPaused;
int get bufferSize => _audioBuffer.length;
audio.PlayerState get playerState => _audioPlayer.state;
int get minBufferSize => _minBufferSize;
int get maxBufferSize => _maxBufferSize;
// ========== 初始化 ==========
Future<void> _init() async {
await _audioPlayer.setPlayerMode(audio.PlayerMode.mediaPlayer); // 使用mediaPlayer模式支持字节源
await _audioPlayer.setReleaseMode(audio.ReleaseMode.stop);
await _audioPlayer.setVolume(0.8); // 设置适当音量消除电流麦
print('🎵 AudioManager 初始化完成 - 媒体播放器模式,音量0.8');
}
// ========== 公共方法 ==========
/// 添加音频流数据块
Future<void> addStreamChunk(Uint8List chunk) async {
await _playLock.synchronized(() async {
if (!_isStreamMode) {
await _startStreamPlaybackInternal();
}
_audioBuffer.addAll(chunk);
print(
'📦 添加音频块: ${chunk.length} bytes, 总缓冲: ${_audioBuffer.length} bytes');
_startStreamCompletionTimer();
// 快速启动机制:第一次收到数据且有足够音频时立即播放
if (!_hasStartedPlaying && !_isPlaying && _audioBuffer.length >= 8192) { // 8KB快速启动
print('🚀 快速启动播放: ${_audioBuffer.length} bytes');
_hasStartedPlaying = true;
await _playBufferedAudio();
}
// 优先检查是否达到最大缓冲
else if (!_isPlaying && _audioBuffer.length >= _maxBufferSize) {
print('📊 缓冲区达到最大值 ($_maxBufferSize bytes),开始播放');
await _playBufferedAudio();
}
// 其次检查是否达到最小缓冲
else if (!_isPlaying && _audioBuffer.length >= _minBufferSize) {
print('📊 缓冲区达到最小值 ($_minBufferSize bytes),开始播放');
await _playBufferedAudio();
}
});
}
/// 标记流式播放完成(不再接收新数据)
Future<void> finishStreamPlayback() async {
await _playLock.synchronized(() async {
if (!_isStreamMode || _streamFinished) return;
print('🏁 标记流式播放完成,等待剩余音频播放完毕...');
_streamFinished = true;
_streamCompletionTimer?.cancel();
_streamCompletionTimer = null;
// 如果没有正在播放且缓冲区为空,立即停止
if (!_isPlaying && _audioBuffer.isEmpty) {
await _stopStreamPlaybackInternal();
print('✅ 流式播放完成');
}
// 如果有数据但没在播放,播放剩余数据
else if (!_isPlaying && _audioBuffer.isNotEmpty) {
await _playBufferedAudio();
}
// 如果正在播放,等待播放完成回调处理剩余数据
});
}
/// 暂停播放
Future<void> pause() async {
await _playLock.synchronized(() async {
if (_isPlaying && !_isPaused) {
await _audioPlayer.pause();
_isPaused = true;
print('⏸️ 音频已暂停');
}
});
}
/// 恢复播放
Future<void> resume() async {
await _playLock.synchronized(() async {
if (_isPlaying && _isPaused) {
await _audioPlayer.resume();
_isPaused = false;
print('▶️ 音频已恢复');
}
});
}
/// 立即停止当前流播放
Future<void> forceStopStream() async {
await _playLock.synchronized(() async {
await _forceStopInternal();
});
}
/// 释放资源
Future<void> dispose() async {
await _playLock.synchronized(() async {
await _forceStopInternal();
await _audioPlayer.dispose();
print('🗑️ AudioManager 资源已释放');
});
}
// ========== 内部方法 ==========
Future<void> _startStreamPlaybackInternal() async {
if (_isStreamMode) {
print('⚠️ 检测到正在进行的流式播放,先停止旧的流');
await _forceStopInternal();
await Future.delayed(_playerResetDelay);
// 状态稳定延迟确保旧流完全停止
await Future.delayed(_stateStabilizationDelay);
}
print('🎵 开始流式播放会话');
_isStreamMode = true;
_isPlaying = false;
_isPaused = false;
_streamFinished = false;
_hasStartedPlaying = false; // 重置快速启动标志
_audioBuffer.clear();
_streamCompleter = Completer<void>();
await _resetPlayer();
_startStreamCompletionTimer();
}
void _startStreamCompletionTimer() {
_streamCompletionTimer?.cancel();
_streamCompletionTimer = Timer(_streamCompletionDelay, () async {
await _playLock.synchronized(() async {
if (_isStreamMode && _audioBuffer.isNotEmpty && !_isPlaying) {
print('⏰ 流结束定时器触发,播放剩余数据 (${_audioBuffer.length} bytes)');
await _playBufferedAudio();
}
});
});
}
Future<void> _playBufferedAudio() async {
if (_isPlaying || _audioBuffer.isEmpty) return;
_isPlaying = true;
_isPaused = false;
try {
final bytesToPlay = _audioBuffer.length > _maxBufferSize
? _audioBuffer.sublist(0, _maxBufferSize)
: _audioBuffer;
final audioData = Uint8List.fromList(bytesToPlay);
if (_audioBuffer.length > _maxBufferSize) {
_audioBuffer.removeRange(0, _maxBufferSize);
} else {
_audioBuffer.clear();
}
print(
'▶️ 开始播放 ${audioData.length} bytes, 剩余缓冲: ${_audioBuffer.length} bytes');
await _safePlay(audioData);
_setupPlaybackCompletionListener();
} catch (e) {
print('❌ 播放音频时出错: $e');
await _handlePlaybackError();
}
}
void _setupPlaybackCompletionListener() {
_audioPlayer.onPlayerComplete.first.then((_) async {
await _playLock.synchronized(() async {
// 状态稳定延迟确保状态一致性
await Future.delayed(_stateStabilizationDelay);
_isPlaying = false;
_isPaused = false;
if (_audioBuffer.isNotEmpty) {
print('🔄 播放完成,检查新数据: ${_audioBuffer.length} bytes 待播放');
// 立即播放下一段,保持流畅性
await _playBufferedAudio();
} else if (_streamFinished) {
// 所有数据已播放完毕,完成流式播放
await _stopStreamPlaybackInternal();
print('✅ 所有音频数据播放完成');
}
});
}).catchError((e) async {
print('❌ 播放完成监听错误: $e');
await _playLock.synchronized(() async {
_isPlaying = false;
_isPaused = false;
// 错误时也需要状态稳定延迟
await Future.delayed(_stateStabilizationDelay);
});
});
}
Future<void> _safePlay(Uint8List audioData) async {
try {
// 确保播放器状态一致性
await _audioPlayer.stop();
await Future.delayed(_playerResetDelay);
// 状态稳定延迟消除电流麦
await Future.delayed(_stateStabilizationDelay);
await _audioPlayer.setSourceBytes(audioData);
// 再次确保状态稳定
await Future.delayed(_stateStabilizationDelay);
await _audioPlayer.resume();
_isPaused = false;
} catch (e) {
print('❌ 安全播放失败: $e');
await _handlePlaybackError();
rethrow;
}
}
Future<void> _stopStreamPlaybackInternal() async {
if (!_isStreamMode) return;
print('⏹️ 停止流式播放');
_isStreamMode = false;
_isPlaying = false;
_isPaused = false;
_streamFinished = false;
_hasStartedPlaying = false; // 重置快速启动标志
_audioBuffer.clear();
_streamCompletionTimer?.cancel();
_streamCompletionTimer = null;
try {
await _audioPlayer.stop();
// 状态稳定延迟确保播放器完全停止
await Future.delayed(_stateStabilizationDelay);
} catch (e) {
print('停止播放器时出错: $e');
}
if (_streamCompleter != null && !_streamCompleter!.isCompleted) {
_streamCompleter!.complete();
}
_streamCompleter = null;
}
Future<void> _forceStopInternal() async {
print('🛑 强制停止当前音频流');
_isStreamMode = false;
_isPlaying = false;
_isPaused = false;
_streamFinished = false;
_hasStartedPlaying = false; // 重置快速启动标志
_audioBuffer.clear();
_streamCompletionTimer?.cancel();
_streamCompletionTimer = null;
try {
await _audioPlayer.stop();
// 状态稳定延迟确保强制停止完全生效
await Future.delayed(_stateStabilizationDelay);
} catch (e) {
print('强制停止播放器时出错: $e');
}
if (_streamCompleter != null && !_streamCompleter!.isCompleted) {
_streamCompleter!.complete();
}
_streamCompleter = null;
}
Future<void> _resetPlayer() async {
try {
await _audioPlayer.stop();
await Future.delayed(_playerResetDelay);
// 状态稳定延迟确保播放器完全重置
await Future.delayed(_stateStabilizationDelay);
} catch (e) {
print('重置播放器时出错: $e');
}
}
Future<void> _handlePlaybackError() async {
_isPlaying = false;
_isPaused = false;
try {
await _resetPlayer();
// 错误处理后的状态稳定延迟
await Future.delayed(_stateStabilizationDelay);
} catch (e) {
print('重置播放器失败: $e');
}
}
Future<double> getAudioDuration(Uint8List audioData) async {
try {
await _audioPlayer.setSourceBytes(audioData);
final duration = await _audioPlayer.getDuration();
return duration != null ? duration.inMilliseconds / 1000.0 : 0;
} catch (e) {
print('获取音频时长失败: $e');
return 0;
} finally {
await _audioPlayer.stop();
}
}
}