美文网首页iOS开发攻城狮的集散地iOS学习笔记视频音频
AVPlayer(seekToTime) 拒绝卡顿,畅享丝滑

AVPlayer(seekToTime) 拒绝卡顿,畅享丝滑

作者: Genie_GY | 来源:发表于2018-08-24 18:07 被阅读29次
    背景:AVPlayer播放视频时,可通过seekToTime:方法跳转到视频指定时间,通常会绑定进度条通过拖动来实现。细心的人会发现,当拖动是前进方向时,视频画面是非常流畅的,反之拖动后退时,就会出现卡顿,卡顿的程度与视频质量、长度等或有关系。(卡顿原因有待思考,知道的读者望评论告知)
    时间进度条
    解决方法:我为AVPlayer写了一个分类(SeekSmoothly),使用ss_seekToTime:替换原本的seekToTime:方法便可。源码如下:

    `

    AVPlayer+SeekSmoothly.h
    #import <AVFoundation/AVFoundation.h>
    
    @interface AVPlayer (SeekSmoothly)
    
    - (void)ss_seekToTime:(CMTime)time;
    
    - (void)ss_seekToTime:(CMTime)time
          toleranceBefore:(CMTime)toleranceBefore
           toleranceAfter:(CMTime)toleranceAfter
        completionHandler:(void (^)(BOOL))completionHandler;
    
    @end
    
    AVPlayer+SeekSmoothly.m
    #import "AVPlayer+SeekSmoothly.h"
    #import <objc/runtime.h>
    
    @interface AVPlayerSeeker : NSObject
    {
        CMTime targetTime;
        BOOL isSeeking;
    }
    
    @property (weak, nonatomic) AVPlayer *player;
    
    @end
    
    @implementation AVPlayerSeeker
    
    - (instancetype)initWithPlayer:(AVPlayer *)player {
        self = [super init];
        if (self) {
            self.player = player;
        }
        return self;
    }
    
    - (void)seekSmoothlyToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
        targetTime = time;
        if (!isSeeking) {
            [self trySeekToTargetTimeWithToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
        }
    }
    
    - (void)trySeekToTargetTimeWithToleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
        if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
            [self seekToTargetTimeToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
        }
    }
    
    - (void)seekToTargetTimeToleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
        isSeeking = YES;
        CMTime seekingTime = targetTime;
        [self.player seekToTime:seekingTime toleranceBefore:toleranceBefore
                 toleranceAfter:toleranceAfter completionHandler:
         ^(BOOL isFinished) {
             if (CMTIME_COMPARE_INLINE(seekingTime, ==, targetTime)) {
                 // seek completed
                 isSeeking = NO;
                 if (completionHandler) {
                     completionHandler(isFinished);
                 }
             } else {
                 // targetTime has changed, seek again
                 [self trySeekToTargetTimeWithToleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
             }
         }];
    }
    
    @end
    
    
    static NSString *seekerKey = @"ss_seeker";
    
    @implementation AVPlayer (SeekSmoothly)
    
    - (void)ss_seekToTime:(CMTime)time {
        [self ss_seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:nil];
    }
    
    - (void)ss_seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL))completionHandler {
    
        AVPlayerSeeker *seeker = objc_getAssociatedObject(self, &seekerKey);
        if (!seeker) {
            seeker = [[AVPlayerSeeker alloc] initWithPlayer:self];
            objc_setAssociatedObject(self, &seekerKey, seeker, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
    
        [self pause];
        [seeker seekSmoothlyToTime:time toleranceBefore:toleranceBefore toleranceAfter:toleranceAfter completionHandler:completionHandler];
    }
    
    @end
    

    `

    简析源码:

    分类中通过运行时关联AVPlayerSeeker对象,
    在AVPlayerSeeker中记录seek状态isSeeking,避免AVPlayer seekToTime:方法同时多次调用,
    并记录目标时间targetTime,保证最后视频正确跳转。

    相关文章

      网友评论

        本文标题:AVPlayer(seekToTime) 拒绝卡顿,畅享丝滑

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