MAUI应用中按顺序播放byte[]音频及中途停止方案咨询
MAUI 音频顺序播放+中途停止实现方案
你的问题出在foreach循环里直接批量创建播放器并调用Play,所有音频会异步启动导致叠加播放。要实现顺序播放,需要在上一个音频播放结束后再启动下一个,同时维护播放状态来支持中途停止。
核心实现思路
- 维护当前播放索引和停止标志,控制播放流程
- 利用
PlaybackEnded事件触发下一个音频的播放 - 停止时终止当前播放并重置状态
具体代码修改
1. 页面/ViewModel 层逻辑
首先添加几个状态变量:
private int _currentPlayIndex = -1; private bool _isStopRequested = false; private VoicePlayer _currentVoicePlayer; private ObservableCollection<YourRecordModel> VoiceAudioCollection; // 你的音频集合(替换成实际模型类)
然后编写顺序播放的核心方法:
// 启动顺序播放 public void StartSequentialPlayback() { _isStopRequested = false; _currentPlayIndex = -1; PlayNextAudio(); } // 播放下一个音频 private void PlayNextAudio() { if (_isStopRequested) { ResetPlayState(); return; } _currentPlayIndex++; if (_currentPlayIndex >= VoiceAudioCollection.Count) { // 所有音频播放完毕 ResetPlayState(); return; } var currentRecord = VoiceAudioCollection[_currentPlayIndex]; currentRecord.IsPlaying = true; _currentVoicePlayer = new VoicePlayer(currentRecord.FileBytes); _currentVoicePlayer.PlaybackEnded += OnPlaybackEnded; _currentVoicePlayer.Play(); } // 播放结束回调 private void OnPlaybackEnded(object sender, EventArgs args) { var currentRecord = VoiceAudioCollection[_currentPlayIndex]; currentRecord.IsPlaying = false; _currentVoicePlayer?.Dispose(); // 释放播放器资源 _currentVoicePlayer = null; Console.WriteLine($"*** PLAYBACK ENDED *** {currentRecord.Id}"); // 继续播放下一个 PlayNextAudio(); } // 中途停止播放 public void StopPlayback() { _isStopRequested = true; _currentVoicePlayer?.Stop(); ResetPlayState(); } // 重置播放状态 private void ResetPlayState() { if (_currentPlayIndex >= 0 && _currentPlayIndex < VoiceAudioCollection.Count) { VoiceAudioCollection[_currentPlayIndex].IsPlaying = false; } _currentVoicePlayer?.Dispose(); _currentVoicePlayer = null; _currentPlayIndex = -1; }
2. 平台端 VoicePlayer 完善
确保你的VoicePlayer实现了Stop方法并正确触发PlaybackEnded事件:
iOS 端
private AVFoundation.AVAudioPlayer player; private bool _isPlaying; public event EventHandler PlaybackEnded; public void Play() { _isPlaying = true; player.Play(); } public void Stop() { if (player?.IsPlaying ?? false) { player.Stop(); _isPlaying = false; } } // 重写AVAudioPlayerDelegate的播放结束回调 public override void DidFinishPlaying(AVAudioPlayer player, bool successfully) { _isPlaying = false; PlaybackEnded?.Invoke(this, EventArgs.Empty); }
Android 端
private Android.Media.MediaPlayer player; private bool _isPlaying; public event EventHandler PlaybackEnded; public VoicePlayer(byte[] fileBytes) { // 初始化player的原有代码... // 订阅播放完成事件 player.Completion += (s, e) => { _isPlaying = false; PlaybackEnded?.Invoke(this, EventArgs.Empty); }; } public void Play() { if (!_isPlaying) { _isPlaying = true; player.Start(); } } public void Stop() { if (_isPlaying && player?.IsPlaying ?? false) { player.Stop(); player.SeekTo(0); // 重置到开头,方便后续重新播放 _isPlaying = false; } }
关键注意事项
- 播放结束或停止时必须释放播放器资源,避免内存泄漏
- 如果
VoiceAudioCollection有动态增减的情况,需要额外处理索引越界问题 - 平台端必须确保
PlaybackEnded事件在播放完成时正确触发,这是顺序播放的核心触发点
内容的提问来源于stack exchange,提问作者Reza
相关产品推荐
相关产品推荐

