In my project, I am using a Kolada view (here) to present a stack of cards, each with a video on them. Sometimes when I am loading the next video, My AVPlayer fails to play a video, it will just show the first frame and be frozen. I am using several observers to track when the video will actually play, if it is likely to keep up with playback. Could observers cause playback to freeze if they are not properly deallocated? If not, What else causes playback for AVPlayer to freeze?
UPDATE: I've noticed that playbackLikelyToKeepUp is never called sometimes, and when this happens, the AVPlayer then never calls it again even if I change the player item. Thus video playing never resumes.
init(frame: CGRect, mediaURL: NSURL, thumbURL: NSURL?, isLoop: Bool) {
self.mediaURL = mediaURL
self.isLoop = isLoop
let asset = AVAsset(URL: mediaURL)
let item = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: item)
player!.actionAtItemEnd = .None
super.init(frame: frame)
asset.loadValuesAsynchronouslyForKeys(["duration"], completionHandler: { () -> Void in
var error: NSError?
let keyStatus: AVKeyValueStatus = asset.statusOfValueForKey("duration", error: &error)
switch (keyStatus) {
case .Loaded:
let duration: CMTime = asset.duration
self.currentDuration = duration
self.delegate?.updateDuration()
default:
break
}
})
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(MediaPlayerView.playerItemDidReachEnd(_:)),
name: AVPlayerItemDidPlayToEndTimeNotification,
object: player!.currentItem)
self.timeObserver = self.player!.addPeriodicTimeObserverForInterval(CMTimeMakeWithSeconds(1.0 / 30.0, Int32(NSEC_PER_SEC)), queue: nil, usingBlock: {
[weak self] (time) -> Void in
if time.value > 0 {
self?.spinnerView?.stopAnimating()
if(self?.player != nil){
if(self?.player!.rate > 0){
self?.placeholderImageView?.hidden = true
}
}
let timeInSeconds = CMTimeGetSeconds(time)
self?.delegate?.playbackReachedTime(timeInSeconds)
}
})
player!.currentItem?.addObserver(self, forKeyPath: playbackLikelyToKeepUp, options: .New, context: &observationContext)
player!.addObserver(self, forKeyPath: "rate", options: .New, context: &observationContext)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MediaPlayerView.playerIsTapped(_:)))
addGestureRecognizer(tapGesture)
}
Use the replaceCurrentItemWithPlayerItem on an existing instance of an AVPlayer object, setting the value to nil to destroy it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With