AVPlayer : How to handle network interruptions

后端 未结 3 1054
旧巷少年郎
旧巷少年郎 2020-12-24 15:27

When using AVPlayer to play audio from an url it will discontinue to play when for example disconnecting from wifi.

[pl         


        
相关标签:
3条回答
  • 2020-12-24 16:08

    You should add observer for AVPlayerItemPlaybackStalledNotification.

    AVPlayerItemFailedToPlayToEndTimeNotification has no value for me on this problem.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStalled:) name:AVPlayerItemPlaybackStalledNotification object:trackItem];
    

    As the doc says, file-based playback does not continue if necessary streaming media wasn’t delivered in a timely fashion over a network.

    The notification’s object is the AVPlayerItem instance whose playback was unable to continue because the necessary streaming media wasn’t delivered in a timely fashion over a network. Playback of streaming media continues once a sufficient amount of data is delivered. File-based playback does not continue.

    This explained why AVPlayer can resume HLS streams after network switch, but cannot do the same if I use AVPlayer to play TuneIn resources which is file-based.

    Then the answer becomes simple.

    - (void)playbackStalled:(NSNotification *)notification {
        if ([self isFileBased:streamUri]) {
            // Restart playback
            NSURL *url = [NSURL URLWithString:streamUri];
            AVPlayerItem *trackItem = [AVPlayerItem playerItemWithURL:url];
            AVPlayer *mediaPlayer = [AVPlayer playerWithPlayerItem:trackItem];
            [self registerObservers:trackItem player:mediaPlayer];
            [mediaPlayer play];
        }
    }
    

    Further reading on discussion of automaticallyWaitsToMinimizeStalling.

    0 讨论(0)
  • 2020-12-24 16:26

    0xced's answer for Swift 3/4:

    var playerItem: AVPlayerItem?
    var player: AVPlayer?
    
    func instantiatePlayer(_ url: URL) {
        self.playerItem = AVPlayerItem(url: url)            
        self.player = AVPlayer(playerItem: self.playerItem)
            NotificationCenter.default.addObserver(self, selector: #selector(playerItemFailedToPlay(_:)), name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, object: nil)
    }
    
    func playerItemFailedToPlay(_ notification: Notification) {
        let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error
    
    }
    
    0 讨论(0)
  • 2020-12-24 16:28

    In order to handle network changes, you have to add an observer for AVPlayerItemFailedToPlayToEndTimeNotification.

    - (void) playURL:(NSURL *)url
    {
        AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFailedToPlayToEndTime:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
        self.player = [AVPlayer playerWithPlayerItem:playerItem];
        [self.player play];
    }
    
    - (void) playerItemFailedToPlayToEndTime:(NSNotification *)notification
    {
        NSError *error = notification.userInfo[AVPlayerItemFailedToPlayToEndTimeErrorKey];
        // Handle error ...
    }
    
    0 讨论(0)
提交回复
热议问题