ios - 在 iOS 上使用 AVAudioPlayer 播放静音的最佳方式
问题描述
我发现自己需要模拟音频播放以欺骗操作系统控件并MPNowPlayingInfoCenter
认为正在播放音频。这是因为我正在构建一个播放多个音轨的播放器,在创建一个连续的“音频”音轨之间有暂停。我已经在应用程序本身内进行了所有设置,并且锁屏控件工作正常,但我面临的唯一问题是,当实际音频停止并且正在“播放”暂停时,锁屏信息中心会停止计时器,并且一旦另一个音轨开始播放,它只会继续显示正确的时间和整体状态。
这是我从音频文件和暂停项目构建的音轨示例:
let items: [AudioItem] = [
.audio("part-1.mp3"),
.pause(duration: 5), // value of type: TimeInterval
.audio("part-2.mp3"),
.pause(duration: 3),
... // the list goes on
]
然后在我的自定义播放器中,一旦AVAudioPlayer
完成当前项目的工作,我会从数组中获取下一个并播放 a.pause
与预定Timer
或另一个.audio
与AVAudioPlayer
.
extension Player: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
playNextItem()
}
}
问题就在这里,一旦AVAudioPlayer
停止,正在播放的信息中心也会自动停止,即使我一直在喂它新鲜nowPlayingInfo
。然后当它碰到另一个.audio
项目时,它会正确恢复并显示当前时间等。
这就是问题所在
如何MPNowPlayingInfoCenter
在我“播放”我的项目时让他们认为正在播放音频.pause
?
我意识到,我想要实现的目标可能仍然不清楚,但如果需要,我很乐意分享更多见解。谢谢!
我目前正在考虑的一些解决方案:
A. 保持 1 秒长的空音轨,只要需要暂停播放,就会循环播放。
B.以适当的长度以编程方式创建空音轨并播放它,而不是Timer
用于跟踪暂停持续时间/进度,并完全依赖 AVAudioPlayer.audio
和.pause
项目。虽然不确定这是可能的。
C. 也许有一种方法可以告诉MPNowPlayingInfoCenter
音频在不需要使用AVAudioPlayer
但我不熟悉的一些 API 的情况下继续播放?
解决方案
AVAudioPlayer 在这里可能是错误的工具。您需要 AVAudioPlayerNode,它的级别略低。创建一个 AVAudioEngine,并附加一个AVAudioPlayerNode。然后,您可以scheduleFile(_:at:completionHandler:)
在需要的时间拨打电话播放音频。
大部分关于AVAudioEngine的 Apple 文档此时似乎都已损坏,但希望这些链接很快会在Audio Engine Building Blocks的链接中再次可用。(如果它一直处于关闭状态并且您无法找到文档,请发表评论,我将搜索 WWDC 视频和其他有关使用 AVAudioEngine 的教程。对于简单的问题并不是特别困难。)
如果您事先知道要如何组合这些项目(看起来您可能会),另请参阅 AVMutableComposition,它可以让您非常有效地将资产粘合在一起,包括添加空的静音片段。有关该空间中的各种工具,请参阅媒体合成和编辑。