AVPlayer.addPeriodicTimeObserver equivalent on AVAudioPlayerNode

890 Views Asked by At

I'am refactoring a react-native package that using AVPlayer, into AVAudioEngine and AVAudioPlayerNode. But I confuse how to turn AVPlayer.addPeriodicTimeObserver using AVAudioPlayerNode. The idea is i need to get time data when music is playing, hence in this addPeriodicTimeObserver closure need to send with interval, so in that regard how to use it on AVAudioPlayerNode, thanks!

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,
            ])
        }
    }
}
2

There are 2 best solutions below

1
On BEST ANSWER

I ended up using timer to observe.

@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
      )
    }
  }
0
On

Please try this, may be solve your point, currentTime will tell avplayer current position

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)
        
    }
    
    
}