首页 > 解决方案 > just_audio 中曲目之间的静音

问题描述

我想在使用 just_audio AudioPlayer 实例创建的播放列表中的轨道之间有一个可变长度的暂停(我想在此间隔期间播放一个背景轨道)。大意是:

_voiceAudioPlayer.currentIndexStream.listen((event) {
  _voiceAudioPlayer.pause();
  Future.delayed(const Duration(seconds: 4), () => _voiceAudioPlayer.play());
});

这会引发错误:

“未处理的异常:错误状态:无法触发新事件。控制器已经在触发事件”

有没有一种干净的方法可以做到这一点?我正在考虑在播放列表中的所有其他曲目中添加静音 mp3,但我觉得应该有更好的方法。

标签: flutterjust-audio

解决方案


发生此错误是因为currentIndexStream是“同步”广播流,因此在处理当前事件时(即在事件循环的同一循环中),您无法触发另一个状态更改事件。但是你可以通过在当前周期之后安排一个微任务来解决这个问题:

_voiceAudioPlayer.currentIndexStream.listen((index) {
  scheduleMicrotask(() async {
    _voiceAudioPlayer.pause();
    await Future.delayed(Duration(seconds: 4));
    _voiceAudioPlayer.play();
  });
});

尽管如此,由于 just_audio 的播放列表的无缝特性,我不会依赖这个回调很快就会执行。也就是说,下一个音轨将立即开始播放,因此在暂停发生之前,您肯定会听到至少一小部分下一个项目的音频。

有一个开放的功能请求SilenceAudioSource可以插入到播放列表中(如果您希望实现它,可以通过单击大拇指按钮来投票支持该问题。)您提出的无声音频文件实际上是最简单的替代SilenceAudioSource.

否则,另一种方法是根本不使用无间隙播放列表功能(因为您不需要无间隙功能),只需实现您自己的逻辑来推进队列:

final queue = [source1, source2, source3, ...];
for (var source in queue) {
  await _voiceAudioPlayer.setAudioSource(source);
  await _voiceAudioPlayer.play();
  await Future.delayed(seconds: 4);
}

上面的示例不处理暂停/恢复逻辑,但这只是为了表明如果您不需要无缝功能,您可以将播放列表逻辑掌握在自己手中。


推荐阅读