在 iOS 上使用 AVAudioPlayer 播放静音的最佳方式

Best way to play silence using AVAudioPlayer on iOS

我发现自己处于一种情况,我需要模拟音频播放来欺骗 OS 控件并 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 完成当前项目的工作,我从数组中获取下一个项目并播放 .pause 和预定的 Timer 或另一个 .audioAVAudioPlayer.

extension Player: AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        playNextItem()
    }
}

问题就在这里,一旦 AVAudioPlayer 停止,“正在播放”信息中心也会自动停止,即使我一直在更新它 nowPlayingInfo。然后当它碰到另一个 .audio 项目时,它会正确恢复并显示当前时间等。

问题就在这里

如何在我“播放”我的 .pause 项目时让 MPNowPlayingInfoCenter 认为正在播放音频?

我意识到我可能还不清楚我正在努力实现什么,但如果需要,我很乐意分享更多见解。谢谢!

目前想到的一些解决方案:

一个。保持 1 秒长的空音轨,只要需要暂停播放就可以循环播放。

乙。创建具有适当长度的编程空音轨并播放它,而不是使用 Timer 来跟踪暂停 duration/progress 并完全依赖 AVAudioPlayer 来处理 .audio.pause 项目。虽然不确定这是否可能。

C。也许有一种方法可以告诉 MPNowPlayingInfoCenter 音频可以继续播放而不需要使用 AVAudioPlayer 但有些 API 我不熟悉?

AVAudioPlayer 可能是这里的错误工具。您需要 AVAudioPlayerNode,它的级别稍低。创建一个 AVAudioEngine,并附加一个 AVAudioPlayerNode。然后您可以调用 scheduleFile(_:at:completionHandler:) 在您想要的时间播放音频。

AVAudioEngine appears broken right this moment, but the links hopefully will be available again shortly in the links for Audio Engine Building Blocks 上的大部分 Apple 文档。 (如果它保持关闭并且您找不到文档,请发表评论,我会搜索 WWDC 视频和其他有关使用 AVAudioEngine 的教程。对于简单的问题来说并不是特别困难。)

如果您事先知道要如何组合这些项目(看起来您可能会),另请参阅 AVMutableComposition,它可以让您非常有效地将资产粘合在一起,包括添加空的静音段。有关 space 中的各种工具,请参阅 Media Composition and Editing