AVPlayer.addPeriodicTimeObserver 相当于 AVAudioPlayerNode

AVPlayer.addPeriodicTimeObserver equivalent on AVAudioPlayerNode

我正在将使用 AVPlayer 的 react-native 包重构为 AVAudioEngine 和 AVAudioPlayerNode。但是我混淆了如何使用 AVAudioPlayerNode 来转 AVPlayer.addPeriodicTimeObserver。这个想法是我需要在播放音乐时获取时间数据,因此在这个 addPeriodicTimeObserver 闭包中需要间隔发送,所以在这方面如何在 AVAudioPlayerNode 上使用它,谢谢!

func addPeriodicTimeObserver() {
    let timeScale = CMTimeScale(NSEC_PER_SEC)
    let time = CMTime(seconds: subscriptionDuration, preferredTimescale: timeScale)
  
    timeObserverToken = audioPlayer.addPeriodicTimeObserver(forInterval: time,
                                                            queue: .main) {_ in
        if (self.audioPlayer != nil) {
            self.sendEvent(withName: "rn-playback", body: [
                "isMuted": self.audioPlayer.isMuted,
                "currentPosition": self.audioPlayerItem.currentTime().seconds * 1000,
                "duration": self.audioPlayerItem.duration.seconds * 1000,
            ])
        }
    }
}

请试试这个,可能会解决你的问题,currentTime 会告诉 avplayer 当前位置

let timeScale = CMTimeScale(NSEC_PER_SEC)
let time = CMTime(seconds: 0.01, preferredTimescale: timeScale)
timeObserverToken = player.addPeriodicTimeObserver(forInterval: time,
                                                        queue: .main) {_ in
    
    if (self.player != nil) {
        
        let currentTime = self.player.currentTime().seconds
        print("currentTime",currentTime)
        
    }
    
    
}

最后我用定时器来观察。

@objc(setupPlayer:rejecter:)
  func setupPlayer(
    resolve: @escaping RCTPromiseResolveBlock,
    rejecter reject: @escaping RCTPromiseRejectBlock
  ) {
    ...
    do {
      try engine.start()
      startPlaybackTimer()

    } catch let err {
      ...
    }
  }

  @objc(updatePlaybackProgress:)
  public func updatePlaybackProgress(timer: Timer) -> Void {
    if player.isPlaying {
    
    let status = [
      "currentPosition": getCurrentPos(),
      "duration": getCurrentDuration(),
    ] as [String : Any];
    
      self.sendEvent(withName: "playbackData", body: status)
    }
  }

  @objc(startPlaybackTimer)
  func startPlaybackTimer() -> Void {
    DispatchQueue.main.async {
      self.timer = Timer.scheduledTimer(
        timeInterval: self.subscriptionDuration,
        target: self,
        selector: #selector(self.updatePlaybackProgress),
        userInfo: nil,
        repeats: true
      )
    }
  }