How does AVPlayer / AVPlayerItem inform my applica

2019-03-27 14:10发布

I’m using AVPlayer to implement a custom video player in an iOS application. To play video from the network I allocate a player:

[[AVPlayer alloc] initWithURL:_URL];

Create an asset:

AVURLAsset *asset = [AVURLAsset URLAssetWithURL:self.URL
options:@{AVURLAssetPreferPreciseDurationAndTimingKey : @(YES)}];

load the playable key asynchronously:

NSArray *keys = @[@"playable"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
    dispatch_async(dispatch_get_main_queue(), ^{
        for (NSString *key in keys) {
            NSError *error;
            AVKeyValueStatus status = [asset statusOfValueForKey:key error:&error];

            if (status == AVKeyValueStatusFailed) {
                NSLog(@"Failed to load asset key %@ error %@", key, [error localizedDescription]);
                [self fail];
                return;
            }
        }

        if (asset.isPlayable) {
            [self.player replaceCurrentItemWithPlayerItem:self.playerItem];
        }
        else {
            [self fail];
        }
    });
}];

The problem is that when the device has no internet connection or high packet loss, the completionHandler is never called (even after waiting for minutes) and so I have no idea when to show a message to the user that loading the video failed.

My questions are:

  1. Am I missing something / is there a better way to handle this?
  2. Should I roll my own timeout logic or should I just never loadValuesAsynchronouslyForKeys: when Reachability believes that the network isn't reachable.
  3. What are the best practices regarding AVPlayer and network failures?

3条回答
淡お忘
2楼-- · 2019-03-27 15:10

It turns out that this may have been related to the way I was testing. Using the Network Link conditioner didn't trigger the block, but when I actually blocked the host using Charles Proxy, everything worked as intended. I'm trying to go with my original code for now, and will add in some of Dan's ideas if it proves to be problematic still during real world testing

查看更多
对你真心纯属浪费
3楼-- · 2019-03-27 15:14

You should be observing (KVO) features of the AVPlayerItem that reveal how the buffer is doing, such as playbackBufferEmpty etc.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-03-27 15:14

I've integrated AVAsset before, but haven't run into this specific issue. Nonetheless, here's what I would do:

  1. Set a timer or delayed block dispatch for the length of the timeout you'd like to enforce.
  2. Check the value of the "playable" key with statusOfValueForKey:error:.
  3. If the status is not AVKeyValueStatusLoaded or error is not nil, call [asset cancelLoading] and display an error message to the user or whatever cleanup you might need to do.
查看更多
登录 后发表回答