我想在一个just_audio AudioPlayer实例创建的播放列表中有一个可变长度的暂停(有一个背景轨道,我想在这个间隔期间播放)。大意是:
_voiceAudioPlayer.currentIndexStream.listen((event) {
_voiceAudioPlayer.pause();
Future.delayed(const Duration(seconds: 4), () => _voiceAudioPlayer.play());
});
抛出错误:
"未处理异常:状态不良:无法触发新事件。控制器已经触发一个事件">
是否有一个干净的方法来做到这一点?我正在考虑在播放列表中的其他曲目中添加无声mp3,但我觉得应该有更好的方法。
出现此错误是因为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);
}
上面的例子不处理暂停/恢复逻辑,但它只是为了表明,如果你不需要无间隙特性,你可以把播放列表逻辑掌握在自己手中。