如何在just_audio中实现音频的淡入与淡出效果
just_audio 为 ConcatenatingAudioSource 子项实现淡入淡出的最优方案
方案1:原生内置配置(首选,性能最优)
just_audio 从 0.9.30 版本开始,AudioSource 原生支持单独配置淡入淡出时长,由框架底层直接处理,无额外逻辑开销,适配全平台,是拼接音频流场景下的最优方案。
你不需要修改 ConcatenatingAudioSource 的主逻辑,只需要在构造每个子音频源时单独配置参数即可:
final concatenatedSource = ConcatenatingAudioSource( children: [ // 每个音频项可以单独配置不同的淡入淡出时长 AudioSource.uri( Uri.parse("your_audio_url_1.mp3"), fadeInDuration: const Duration(milliseconds: 300), fadeOutDuration: const Duration(milliseconds: 300), ), AudioSource.uri( Uri.parse("your_audio_url_2.mp3"), fadeInDuration: const Duration(milliseconds: 500), fadeOutDuration: const Duration(milliseconds: 200), ), // 其余音频项 ], );
该方案的淡出逻辑会自动在当前音频播放到末尾前触发,刚好在音频结束时完成淡出,不会和下一个音频的淡入出现冲突。
方案2:手动控制音量(仅适用于自定义触发场景)
如果你需要在非音频结束节点触发淡入淡出(比如用户主动切歌、音频被系统中断等场景),可以通过监听播放状态、结合 Flutter 动画手动调整音量实现:
- 监听
player.currentIndex流感知切歌动作 - 用
AnimationController实现平滑的音量过渡,避免自定义定时器的性能损耗
参考代码:
// 初始化动画控制器,duration为淡入淡出的总时长 final _fadeController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300)); late Animation<double> _fadeAnimation; // 监听播放索引变化 player.currentIndexStream.listen((newIndex) { if (newIndex == null) return; // 先执行上一曲淡出 _fadeAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_fadeController); _fadeAnimation.addListener(() { player.setVolume(_fadeAnimation.value); }); _fadeController.forward(from: 0).then((_) { // 淡出完成后执行下一曲淡入 _fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_fadeController); _fadeAnimation.addListener(() { player.setVolume(_fadeAnimation.value); }); _fadeController.forward(from: 0); }); });
注意使用该方案时,淡入的最终音量需要和用户手动设置的系统音量对齐,不要固定写死为1.0。
避坑提示
- 不要同时开启原生淡入淡出配置和手动音量控制,会出现音量叠加异常
- 无特殊自定义需求优先用原生配置,底层已经完成了不同系统的音频通道适配,兼容性更好
内容的提问来源于stack exchange,提问作者Luke Horton
相关产品推荐
相关产品推荐

