如何避免iOS播放系统提示音时AVAudioSession播放的音频被压低
问题解决方案
问题根因
AudioServicesPlaySystemSound走的是系统独立的音频会话通道,默认会触发全局的音频压低逻辑,对所有活跃的音频会话生效,哪怕是同一个App内的音频也会被duck- 你设置的
.mixWithOthers仅控制你的App音频和其他第三方App的音频的混音逻辑,对系统级的提示音会话不生效 - 模拟器无此问题是因为模拟器的音频会话策略没有完全复刻真机的系统级Ducking逻辑,属于正常的表现差异
.longFormAudio策略本身默认允许系统提示音压低当前App音频,这是系统为长音频场景设计的默认交互逻辑
可行解决方案
方案一(最稳定,推荐):替换系统提示音播放方式
不要使用AudioServicesPlaySystemSound播放提示音,改用AVAudioPlayer加载对应音效资源,和你的主音频走同一个AVAudioSession,完全避开系统会话的duck逻辑:
// 先把1407对应的叮声音效导入到你的项目中,比如命名为ding.wav,也可以直接读取系统内置音效路径 guard let url = URL(string: "/System/Library/Audio/UISounds/sms-received1.caf") else { return } do { let player = try AVAudioPlayer(contentsOf: url) player.play() } catch { print("音效播放失败 \(error)") }
方案二:保留系统提示音播放,修改音频会话配置
如果一定要用AudioServicesPlaySystemSound,可以把音频会话的policy改为.default,同时添加对应选项,注意修改配置要在会话激活前完成:
try AVAudioSession.sharedInstance() .setCategory(.playback, mode: .default, policy: .default, // 替换原来的.longFormAudio options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true)
如果你的业务必须使用.longFormAudio策略,可以在播放提示音前临时调整会话配置,播放完成后恢复:
// 播放前临时调整配置 try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers]) AudioServicesPlaySystemSound(SystemSoundID(1407)) // 延迟1秒后恢复原有长音频配置 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, policy: .longFormAudio, options: []) }
内容的提问来源于stack exchange,提问作者Colin Burke
相关产品推荐
相关产品推荐

