You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:35:15