该应用程序无限循环地播放一些背景音频(wav)。使用
just_audio
包的音频播放是完美的,但切换到 audioplayers
后,所有循环音频现在在重新开始之前都包含短暂的静音间隙。现在的问题是:如何消除差距?
加载和播放文件的代码非常简单:
Future<void> loadAmbient() async {
_audioAmbient = AudioPlayer();
await _audioAmbient!.setSource(AssetSource('audio/ambient.wav'));
await _audioAmbient!.setReleaseMode(ReleaseMode.loop);
}
void playAmbient() async {
if (PlayerState.playing != _audioAmbient?.state) {
await _audioAmbient?.seek(Duration.zero);
_audioAmbient?.resume();
}
}
根据音频播放器文档,这似乎是一个已知问题:
入门文档状态:
注意:无间隙循环音频时有一些注意事项。根据文件格式和平台的不同,当音频播放器使用“循环”功能的本机实现时,播放之间会存在间隙,对于非连续 SFX 可能不会明显,但对于循环歌曲肯定会明显。请查看我们的故障排除指南中的无缝环部分了解更多详细信息。
按照[故障排除指南] (https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md) 的链接显示:
无缝循环
根据文件格式和平台的不同,当音频播放器使用“循环”功能的本机实现时,播放之间会存在间隙,对于非连续的 SFX 可能不会明显,但对于循环歌曲肯定会明显。
TODO(luan):在这里分解替代方案,低延迟模式,音频池,gapless_audioplayer,陶笛等
有趣的是
Depending on the file format and platform, ...
部分,这听起来好像无间隙循环可以以某种方式实现。问题是,怎么办?
非常感谢任何如何使音频完美循环(即没有间隙)的想法。谢谢你。
可以传递这个参数
_audioAmbient = AudioPlayer(mode: PlayerMode.LOW_LATENCY);
如果没有解决,你可以尝试一些新的东西,比如https://pub.dev/packages/ocarina
我是这样修复的: 创建了 2 个玩家,为他们两个设置了资产路径,并创建了在第一个玩家完成之前启动第二个玩家的方法
import 'package:just_audio/just_audio.dart' as audio;
audio.AudioPlayer player1 = audio.AudioPlayer();
audio.AudioPlayer player2 = audio.AudioPlayer();
bool isFirstPlayerActive = true;
StreamSubscription? subscription;
audio.AudioPlayer getActivePlayer() {
return isFirstPlayerActive ? player1 : player2;
}
void setPlayerAsset(String asset) async {
if (isFirstPlayerActive) {
await player1.setAsset("assets/$asset");
await player2.setAsset("assets/$asset");
} else {
await player2.setAsset("assets/$asset");
await player1.setAsset("assets/$asset");
}
subscription?.cancel();
_loopPlayer(getActivePlayer(), isFirstPlayerActive ? player2 : player1);
}
audio.AudioPlayer getActivePlayer() {
return isFirstPlayerActive ? player1 : player2;
}
void _loopPlayer(audio.AudioPlayer player1, audio.AudioPlayer player2) async {
Duration? duration = await player1.durationFuture;
subscription = player1.positionStream.listen((event) {
if (duration != null &&
event.inMilliseconds >= duration.inMilliseconds - 110) {
log('finished');
player2.play();
isFirstPlayerActive = !isFirstPlayerActive;
StreamSubscription? tempSubscription;
tempSubscription = player1.playerStateStream.listen((event) {
if (event.processingState == audio.ProcessingState.completed) {
log('completed');
player1.seek(const Duration(seconds: 0));
player1.pause();
tempSubscription?.cancel();
}
});
subscription?.cancel();
_loopPlayer(player2, player1);
}
});
}
我花了很长时间才解决这个问题,因为任何可用的软件包都不能令人满意地解决该问题。
终于我找到了完美的方法。
使用
ocarina
包。不幸的是,它不再被维护,并且不支持新的 Android。
因此,我们分叉了这个存储库并进行了必要的更改。
存储库:https://github.com/mszakacz/ocarina
它支持 Gradle 1.8.0,因此解决了新 Android 的问题。
使用说明:
在
pubspec.yaml
中添加以下依赖项:
陶笛: git: 网址:https://github.com/mszakacz/ocarina
转到
android/build.gradle
并更新您的 kotlin 版本:
ext.kotlin_version = '1.8.0'
另外 为什么其他包不起作用?
Audioplayers
- 在 Android 上工作,但你可以注意到 iOS 上的差距 (https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md#gapless-looping)
just_audio
- 在 Android 上并非无缝