首页 > 解决方案 > 获取多个 AVAudioPlayerNodes 的播放进度/时间

问题描述

我正在尝试构建一个在不同时间播放多个音频(wav)文件的应用程序。这些 wav 文件可能都有不同的长度以及开始和结束时间。我想在音频播放时获得播放时间进度。

从我见过的所有不同的教程和指南中,当你只播放一个音频文件时,这非常简单,因为你可以从中得到lastRenderTimeAVAudioPlayerNode但在我的例子中,我需要能够支持 1+剪辑在不同的(很可能是同时的)时间开始和结束,所以我不能用一个AVAudioPlayerNode来获取lastRenderTimefrom,所以我需要lastRenderTime从不同AVAudioNode的地方获取,比如引擎的默认输出节点。

我试过这样做,但's中没有明确0的时间。outputNodelastRenderTime

我还尝试engine.outputNode.lastRenderTime在播放之前将类/实例变量设置为正确,然后将其用作一种锚点来确定播放了多长时间,但's中没有明确0的时间,所以这似乎有点不准确。outputNodelastRenderTime

var engine = AVAudioEngine()
var mixer = AVAudioMixerNode()
var playerNodes = [AVAudioPlayerNode]()

func prepare() {
    engine.attach(mixer)
    engine.connect(mixer, to: engine.outputNode, format: nil)

    // Create playernode and add to playerNodes

    for node in playerNodes {
        engine.attach(node)
        engine.connect(node, to: mixer, format: nil)
    }

    try! engine.start()
}

func play() {
    for node in playerNodes {
        // schedule file/segment/buffer
        node.play(at: startTimeForNode)
    }
}

如果我有 3 个两秒的音频文件,它们在前一秒后开始(并相互播放),当我按下播放时,我会期望整个播放的样本或毫秒准确时间,而不是每个音频文件的播放时间。我不确定从哪里获得lastRenderTime或如何使用AVAudioTime,以便在播放所有剪辑时获得实时播放时间,但不是针对每个剪辑。

标签: iosswiftavaudioengine

解决方案


你试过用定时器吗?例如(使用您的节点):

timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {[unowned self] timer in
                for node in playerNodes {
                    let nodeTime = node.lastRenderTime!
                    let playerTime = node.playerTime(forNodeTime: nodeTime)!
                    let secs = Double(playerTime.sampleTime) / playerTime.sampleRate
                    print(secs)
                }

这是工作解决方案:https ://gist.github.com/standinga/f79232adb15e1f867ad1637f47c61003


推荐阅读