AVPlayer 当前播放时间问题 、 seek

2019-07-08  本文已影响0人  monkey姜啦

一、AVPlayer 播放时间问题

AVPlayer 播放时间、总时间提供了两种方式去获取,
一个是监听AVPlayerItem 的currentTime属性值变化,我们可以通过实时监听到的时间变化去做先关UI的改变,所有的监听都要在播放器即将销毁时移除监听,否则会收到一个大的惊喜,crush

- (void)abserverCurrentPlayerItem{
// 监听当前状态
    [self.playerItem addObserver:self forKeyPath:@"status"
                    options:NSKeyValueObservingOptionNew
                    context:nil];
    // 监听当前播放时间变化
    [self.playerItem addObserver:self
                 forKeyPath:@"loadedTimeRanges"
                    options:NSKeyValueObservingOptionNew
                    context:nil];
    // 播放完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didPlayToEndTime:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"status"]) {
        if (self.playerItem.status == AVPlayerItemStatusReadyToPlay) {
    
        }
        else if (self.playerItem.status == AVPlayerItemStatusFailed) {
            self.state = CLPlayerStateFailed;
        }
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        // 计算缓冲进度
        CMTime duration             = self.playerItem.duration;
        CGFloat totalDuration       = CMTimeGetSeconds(duration);
    } else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
        // 当缓冲是空的时候
        NSLog(@"当缓冲是空的时候");
        if (self.playerItem.isPlaybackBufferEmpty) {
            [self bufferingSomeSecond];
        }
    } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
        // 当缓冲好的时候
        NSLog(@"当缓冲好的时候");
        if(!self.isStop){
            if (!_isEnd) {
                [self playVideo];
                self.state = CLPlayerStatePlaying;
            }
        }
    }
}

另一个是播放器的回调,能在回调中获取当前的播放进度和总时长,相对于监听的方式,,我在项目中使用的是这个,感觉比较方便。

- (void) abserverCurrentPlayerTime{
    __weak typeof(self)weakSelf = self;
    [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1,1) queue:nil usingBlock:^(CMTime time) {
        __strong typeof(weakSelf)self = weakSelf;
        AVPlayerItem* currentItem = self.player.currentItem;
        NSArray* loadedRanges = currentItem.seekableTimeRanges;
        if (loadedRanges.count > 0){
            CMTimeRange range = [[loadedRanges objectAtIndex:0] CMTimeRangeValue];
            NSTimeInterval duration = CMTimeGetSeconds(range.start) + CMTimeGetSeconds(range.duration);
            // 当前播放总时间
            NSTimeInterval curDuration = CMTimeGetSeconds(time);
            NSLog(@"eidt player:%g", curDuration);
            self.model.curTime = curDuration;
            self.model.totalTime = duration;
            if (self.callBack) {
                self.callBack(self.model);
            }
        }
    }];
    // 播放完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didPlayToEndTime:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
}

二、AVPlayer seek问题

//seek到第一帧
[self.player seekToTime:CMTimeMake(0, 1)];
[self.player seekToTime:kCMTimeZero toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

//seek 到滑动条滑动到位置
- (void)setProgress:(float)progress{
    _progress = progress;
    [self.player seekToTime:CMTimeMake(progress, 1)];
}

//另一个seek的方法也是比较推荐的方法,当seek完成之后再做播放的操作
       [self.player seekToTime:kCMTimeZero toleranceBefore:(CMTime)kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
            [self.player play];
        }];
      

//弄了很久的问题:因为在外部的block中调用了play方法,使得seek的操作可能没有在主线程中调用,所以导致seek一直没起作用,如下放在主线程调用就OK了。
- (void)play{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.model.isEnd) {
             [self.player seekToTime:kCMTimeZero toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
        }
        [self.player play];
        self.model.isEnd = NO;
        self.model.isPause = NO;
        if (self.callBack) {
            self.callBack(self.model);
        }
    });
}
上一篇下一篇

猜你喜欢

热点阅读