Swift 如何使用AVAudioPlayerNode显示歌曲当前时间和持续时间

Swift 如何使用AVAudioPlayerNode显示歌曲当前时间和持续时间,swift,avfoundation,avaudioplayernode,Swift,Avfoundation,Avaudioplayernode,我正在使用AVAudioPlayerNode制作一个音频播放器,播放一首有一定效果(延迟、音高变化、速率变化等)的歌曲,但我一直坚持显示歌曲的当前时间和持续时间。 AVAudioPlayerNode似乎不像AVAudioPlayer.currentTime或.duration 如果您能帮助我使用AVAudioPlayerNode显示currenttime和duration,我将不胜感激。对于duration,AVAudioFile的.length属性有效。 我将文件中的采样帧数除以采样率(441

我正在使用AVAudioPlayerNode制作一个音频播放器,播放一首有一定效果(延迟、音高变化、速率变化等)的歌曲,但我一直坚持显示歌曲的当前时间和持续时间。 AVAudioPlayerNode似乎不像AVAudioPlayer.currentTime或.duration

如果您能帮助我使用AVAudioPlayerNode显示currenttime和duration,我将不胜感激。

对于duration,AVAudioFile的.length属性有效。 我将文件中的采样帧数除以采样率(44100hz)


对于当前时间,我暂时使用UISlider.value并用示例帧合成值。

对于当前时间,我使用的是:

- (NSTimeInterval)currentTimeInSeconds
{
    AVAudioTime *nodeTime = self.playerNode.lastRenderTime;
    AVAudioTime *playerTime = [self.playerNode playerTimeForNodeTime:nodeTime];

    NSTimeInterval seconds = (double)playerTime.sampleTime / playerTime.sampleRate; 
    return seconds;
}
除了抽象时基中的渲染时间外,播放器节点还通过
playerTimeForNodeTime
将该时间转换为自己的播放时间线。还包括暂停等。

这里是swift:

private func currentTime() -> NSTimeInterval {
    if let nodeTime: AVAudioTime = myAvAudioPlayer.lastRenderTime, playerTime: AVAudioTime = myAvAudioPlayer.playerTimeForNodeTime(nodeTime) {
       return Double(Double(playerTime.sampleTime) / playerTime.sampleRate)
    }
    return 0
}
只需用您的AvaudioLayerNode替换MyAvaudioLayer


快乐编码

对于
AVAudioPlayerNode
SWIFT 4:

func durationOfNodePlayer(_ fileUrl: URL) -> TimeInterval {
    do {

        let file = try AVAudioFile(forReading: fileUrl)
        let audioNodeFileLength = AVAudioFrameCount(file.length)
        return Double(Double(audioNodeFileLength) / 44100) //Divide by the AVSampleRateKey in the recorder settings

       } catch {

          return 0
       }

}

像这样的东西应该给你那种能力

extension AVAudioPlayerNode {
    var currentTime: TimeInterval {
    get {
        if let nodeTime: AVAudioTime = self.lastRenderTime, let playerTime: AVAudioTime = self.playerTime(forNodeTime: nodeTime) {
            return Double(playerTime.sampleTime) / playerTime.sampleRate
        }
        return 0
    }
}
Swift 5:

func durationOfNodePlayer(_ fileUrl: URL) -> TimeInterval {
    do {

        let file = try AVAudioFile(forReading: fileUrl)
        let audioNodeFileLength = AVAudioFrameCount(file.length)
        return Double(Double(audioNodeFileLength) / 44100) //Divide by the AVSampleRateKey in the recorder settings

       } catch {

          return 0
       }

}
持续时间,使用
AVAudioPlayrtNode
AVAudioFile

extension AVAudioFile{

    var duration: TimeInterval{
        let sampleRateSong = Double(processingFormat.sampleRate)
        let lengthSongSeconds = Double(length) / sampleRateSong
        return lengthSongSeconds
    }

}


那么当前时间:

extension AVAudioPlayerNode{

    var current: TimeInterval{
        if let nodeTime = lastRenderTime,let playerTime = playerTime(forNodeTime: nodeTime) {
            return Double(playerTime.sampleTime) / playerTime.sampleRate
        }
        return 0
    }
}

谢谢@Brian Becker

@KeitaBickOhshiro如果它对您有效,您可以将答案标记为正确,或者向上投票以使其他成员可见。这会给出实际位置,但如果您选择AudioNode.ScheduleSegment(…)则位置不会重置为0,它只会继续计数。如何解决此问题,@DanielDirtyNativeMartin。请回复此选项仅在节点正在播放时才有效。如果停止,它将返回零。效果非常好,非常感谢您的回答!