Reputation: 312
I playback a video asset via avplayer
and want to perform an action when the item has finished playing. For some reason, playerItemDidReachEnd
doesn't get called and I'm completely lost as to why. I've also tried addPeriodicTimeObserver
to the player and sometimes it works, sometimes it doesn't.
Below is my code. Any guidance would be appreciated.
func setupVideo(with asset: AVAsset) {
let video = AVPlayerItem(asset: asset)
video.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: nil)
avPlayerPlayback.replaceCurrentItem(with: video)
avPlayerPlayback.actionAtItemEnd = .none
let playbackLayer = AVPlayerLayer(player: avPlayerPlayback)
playbackLayer.frame = capturedVideoPlaybackView.frame
playbackLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
capturedVideoPlaybackView.layer.addSublayer(playbackLayer)
print("Player status: \(avPlayerPlayback.status.rawValue)")
print("Player item duration: \(CMTimeGetSeconds(avPlayerPlayback.currentItem?.duration ?? CMTime.zero))")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "status" {
if let item = object as? AVPlayerItem {
if item.status == .readyToPlay {
// The AVPlayerItem is ready to play
print("Item is ready to play")
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: .AVPlayerItemDidPlayToEndTime,
object: self.avPlayerPlayback.currentItem)
self.toggleMedia(shouldHideVideo: false)
self.playVideo()
print("Player status: \(avPlayerPlayback.status.rawValue)")
print("Player item duration: \(CMTimeGetSeconds(avPlayerPlayback.currentItem?.duration ?? CMTime.zero))")
print("playing video")
}
// Perform any additional setup or start playback
} else if item.status == .failed {
// Handle failure
print("Player item failed: \(String(describing: item.error?.localizedDescription))")
}
}
}
}
func playVideo() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
// self.avPlayerPlaybackTimeObserver =
//
// self.avPlayerPlayback.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 2) , queue: .main, using: { time in
//
// if let currentItem = self.avPlayerPlayback.currentItem {
//
// let totalDuration = CMTimeGetSeconds(currentItem.duration)
// let secondsElapsed = CMTimeGetSeconds(time)
//
// print(totalDuration)
// print(secondsElapsed)
//
// let progress = CGFloat(secondsElapsed / totalDuration)
//
// if progress >= 1 {
// self.handlePlaybackItemCompletion()
// }
// }
// })
self.avPlayerPlayback.play()
}
}
@objc func playerItemDidReachEnd(notification: Notification) {
// This function is called when the AVPlayer finishes playing the item
print("Playback finished")
handlePlaybackItemCompletion() // Call your completion handling method
}
Upvotes: 0
Views: 40