Warm tip: This article is reproduced from serverfault.com, please click

audio-Flutter just_audio循环模式未循环

(audio - Flutter just_audio loop mode is not looping)

发布于 2020-11-29 06:39:23

我正在使用flutter audio_service(https://pub.dev/packages/audio_service)和just_audio(https://pub.dev/packages/just_audio)在前景和背景中播放音频文件。

我将BackgroundAudioTask子类化,添加了AudioPlayer的实例,并覆盖了所需的方法。例如,我更新了重复模式:

@override
  Future<void> onSetRepeatMode(AudioServiceRepeatMode repeatMode) async {
    super.onSetRepeatMode(repeatMode);
    switch (repeatMode)
    {
      case  AudioServiceRepeatMode.all:
        _audioPlayer.setLoopMode(LoopMode.all);
        break;
      case  AudioServiceRepeatMode.none:
        _audioPlayer.setLoopMode(LoopMode.off);
        break;
      case AudioServiceRepeatMode.one:
        _audioPlayer.setLoopMode(LoopMode.one);
        break;
      case AudioServiceRepeatMode.group:
        _audioPlayer.setLoopMode(LoopMode.all);
        break;
    }
  }

@override
  Future<void> onPlayFromMediaId(String mediaId) async {
    await _audioPlayer.stop();
    // Get queue index by mediaId.
    _queueIndex = _queue.indexWhere((test) => test.id == mediaId);
    // Set url source to _audioPlayer.
    downloadAndPlay(_mediaItem);
  }

我正在尝试添加一个播放列表并有一个音频文件循环,但是似乎丢失了一些,播放了#1曲目后,播放器想从同一#1曲目开始并再次播放。这是我的代码(downloadAndPlay的一部分):

var list=List<AudioSource>();

for (int t=0;t<_queue.length;t++)
  {
    var mi=_queue[t];
    var url = mi.extras['source'];
    list.add(AudioSource.uri(Uri.parse(url)));
  }

D("Loading list with ${list.length} items");
D("Seeking to index : $_queueIndex");
await _audioPlayer.load(ConcatenatingAudioSource(children: list),
    initialIndex: _queueIndex, initialPosition: Duration.zero);
AudioService.updateQueue(_queue);
AudioService.setRepeatMode(AudioServiceRepeatMode.all);
_audioPlayer.play();

我添加了此代码,以检查是否触发了ProcessingState.completed,这意味着它已到达轨道的尽头,但并未触发:

playerEventSubscription = _audioPlayer.playbackEventStream.listen((event) {
  D("audioPlayerTask: playbackEventStream : ${event.processingState}");
  switch (event.processingState) {
    case ProcessingState.ready:
      _setState(state: AudioProcessingState.ready);
      break;
    case ProcessingState.buffering:
      _setState(state: AudioProcessingState.buffering);
      break;
    case ProcessingState.completed:
      _handlePlaybackCompleted();
      break;
    default:
      break;
  }
});
Questioner
AVEbrahimi
Viewed
11
Ryan Heise 2020-12-01 16:12:55

你从未调用过,_audioPlayer.setLoopMode()因此它不会循环。

你还使用了audio_service,但是你的音频代码似乎audio_service的一半内,audio_service的一半具体来说,你的实例_audioPlayer生活在audio_service之外,而你的实现则setRepeatMode生活在audio_service内,并且将无法访问你_audioPlayer在audio_service之外的实例。

将所有音频逻辑封装在audio_service中,以便你的setRepeatMode实现能够引用你的_audioPlayer实例并对其进行调用_audioPlayer.setLoopMode()这实际上就是我们封装(将方法与它们需要操作的数据捆绑在一起)的原因,但是在这种情况下,我们在audio_service中进行封装还有另一个原因,那就是audio_service之外的所有东西都“封装”了随时可能被摧毁。因此,如果你的应用程序转换为后台并且UI被破坏,则你不希望音频逻辑的一半被破坏。如果将它们全部封装在audio_service中,它将能够在UI毁灭后幸存下来,并且由于它是自包含的,因此它具有在后台继续播放音频所需的一切。

而且,事实上,你的应用程序可能想玩的前景音频并不意味着你需要打破封装。这种封装的音频代码完全可以在没有UI的情况下与UI一起运行,因此你实际上不需要更改编程样式即可支持前台情况。