【问题标题】:Best way to play silence using AVAudioPlayer on iOS在 iOS 上使用 AVAudioPlayer 播放静音的最佳方式
【发布时间】:2021-03-14 19:24:12
【问题描述】:

我发现自己需要模拟音频播放以欺骗操作系统控件和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 项目时,它会正确恢复并显示当前时间等。

问题就在这里

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

我意识到我可能还不清楚我想要实现的目标,但如果需要,我很乐意分享更多见解。谢谢!

我目前正在考虑的一些解决方案:

A.保持 1 秒长的空音轨,只要需要暂停播放,就会循环播放。

B.以编程方式创建具有适当长度的空音轨并播放它,而不是使用 Timer 来跟踪暂停持续时间/进度,并完全依赖 AVAudioPlayer 来处理 .audio.pause 项目。不过不确定这是否可行。

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

【问题讨论】:

    标签: ios swift avaudioplayer avkit


    【解决方案1】:

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

    AVAudioEngine 上的大部分 Apple 文档此时似乎已损坏,但希望不久之后可以在Audio Engine Building Blocks 的链接中再次使用这些链接。 (如果它一直关闭并且您无法找到文档,请发表评论,我会搜索 WWDC 视频和其他有关使用 AVAudioEngine 的教程。对于简单的问题来说,这并不是特别困难。)

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

    【讨论】:

    • 感谢您的回答!我会看看这些链接,一旦我得到某种结果,就会回击你。
    • 我用AVMutableComposition 重新实现了整个事情,它按预期工作!非常感谢。