美文网首页
AVPlayer 当前播放时间问题 、 seek

AVPlayer 当前播放时间问题 、 seek

作者: monkey姜啦 | 来源:发表于2019-07-08 10:25 被阅读0次

    一、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);
            }
        });
    }
    

    相关文章

      网友评论

          本文标题:AVPlayer 当前播放时间问题 、 seek

          本文链接:https://www.haomeiwen.com/subject/vhunhctx.html