Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playing stream with bad internet in AVPlayer

When AVPlayer plays an asset that comes from network stream, it pauses when reaches the end of downloaded content.

So, my question is, how to know, that it stopped because of bad network? And how to play it after it downloads, let’s say, next 10 seconds of asset?

like image 256
Alfred Zien Avatar asked Apr 02 '14 13:04

Alfred Zien


3 Answers

You can add an observer to when the AVPlayer gets empty buffer:

[[self.tracksPlayer currentItem] addObserver:self 
                                  forKeyPath:@"playbackBufferEmpty" 
                                     options:NSKeyValueObservingOptionNew
                                     context:nil];

And an observer so you can know when the AVPlayer buffered enough to keep up:

[[self.tracksPlayer currentItem] addObserver:self 
                                  forKeyPath:@"playbackLikelyToKeepUp" 
                                     options:NSKeyValueObservingOptionNew 
                                     context:nil];

Then just check for that in your KVO callback:

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {

   if (object == [self.tracksPlayer currentItem] && 
      [keyPath isEqualToString:@"playbackBufferEmpty"]) {

      if ([self.tracksPlayer currentItem].playbackBufferEmpty) {
          NSLog(@"Buffer Empty"); 
      }
   } else if (object == [self.tracksPlayer currentItem] && 
             [keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {

      if ([self.tracksPlayer currentItem].playbackLikelyToKeepUp) {
          NSLog(@"LikelyToKeepUp");
      }
   }
}
like image 162
Tiago Almeida Avatar answered Nov 14 '22 09:11

Tiago Almeida


For swift

1)
let playbackLikelyToKeepUpContext = UnsafeMutablePointer<(Void)>(nil)
 or
let playbackLikelyToKeepUpContext = UnsafeMutablePointer<(Void)>()

2) //Add Observer

  player.addObserver(self, forKeyPath: "currentItem.playbackLikelyToKeepUp",
                                    options: NSKeyValueObservingOptions.New, context: playbackLikelyToKeepUpContext)
  player.play()

3)

//Add observer
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

        guard keyPath != nil else { // a safety precaution
            super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
            return
        }

        if (context == playbackLikelyToKeepUpContext)
        {
            if (player.currentItem!.playbackLikelyToKeepUp) {
                player.play()
                Utilities.hideHUD(self.view)
            }
            else {
                Utilities.showHUD(self.view)
            }
        }
    }

4) // Remove Observer

override func viewDidDisappear(animated: Bool) {
        player.removeObserver(self, forKeyPath: "currentItem.playbackLikelyToKeepUp")
    }
like image 23
Hardik Thakkar Avatar answered Nov 14 '22 09:11

Hardik Thakkar


Swift 4 changes the way of KVO. Instead of add observer and function separately, we use a closure(block) in one place.

var observers: [NSKeyValueObservation]?
let playerItem = AVPlayerItem(url: YOUR_URL)

let emptyObserver = playerItem.observe(\.isPlaybackBufferEmpty) {
                        [weak self] (object, observedChange) in
                        // show a progress bar 
                        print("isPlaybackBufferEmpty")
                    }

let keepUpObserver = playerItem.observe(\.playbackLikelyToKeepUp) {
                        [weak self] (object, observedChange) in
                        // hide progress bar and keep going 
                        print("playbackLikelyToKeepUp")
                    }

self.observers = [emptyObserver, keepUpObserver]
like image 22
Allen Avatar answered Nov 14 '22 09:11

Allen