【iOS】封装AVPlayer

项目需求,封装了一个AVPlayer

视频播放需要AVPlayer,AVPlayerLayer和AVPlayerItem,AVPlayer负责控制视频播放暂停等controller负责的事情,AVPlayerLayer只负责显示这种view需要处理的事情,而AVPlayerItem则是提供播放源。

新建一个继承NSObject的类

//单例类
+(instancetype)shareManager
{
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        _videoManager = [[VideoManager alloc] init];
    });
    return _videoManager;
}

这里单例只能设置本类单例,之前我有把avplayer也设置单例,后来发现在切换播放源的时候回卡住,只有声音画面不动。

avplayer在设置播放源的时候进行初始化

//添加播放源
-(void)replacePlayitemWithURL:(NSString *)url
{
    self.playerItem = [AVPlayerItem playerItemWithURL:URL(url)];
    _player = [AVPlayer playerWithPlayerItem:self.playerItem];
    self.playStatus = PlayerStatusUnknown;
    //添加通知
    [self addObserverItems];
    
}

播放源在刚添加上的时候并不会立刻播放,在可以播放的时候值会改变,所以需要为avplayeritem添加kvo

[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

并在值发生改变的时候发送通知

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    //playItem的监听
    if ([object class] == [AVPlayerItem class]) {
        //播放状态的监听
        if ([keyPath isEqualToString:@"status"]) {
            //判断是否可以播放
            if ([change[@"new"] intValue] == AVPlayerStatusReadyToPlay) {
                self.canPlay = YES;
                //block通知
                if (self.readyToPlay) {
                    self.readyToPlay();
                }
            }
        }
    }
    
    //改变状态
    [self changeStatus];
}

这里定义了一个枚举类型,用来判断当前item播放状态

typedef NS_ENUM(NSInteger, PlayerStatus) {
    PlayerStatusUnknown,     ///<初始化
    PlayerStatusPlaying,     ///<播放中
    PlayerStatusPause,     ///<暂停
    PlayerStatusEnd,     ///<播放完成
    PlayerStatusError,     ///<播放错误
    PlayerStatusBuffering   ///<缓冲
};


//改变状态
-(void)changeStatus{
    
    if (_player.error != nil || self.playerItem.error != nil) {
        self.playStatus = PlayerStatusError;
        return;
    }
    
    if IOS(10.0) {
        switch (_player.timeControlStatus){
            case AVPlayerTimeControlStatusPaused:
                self.playStatus = PlayerStatusPause;
                break;
            case AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate:
                self.playStatus = PlayerStatusBuffering;
                break;
            case AVPlayerTimeControlStatusPlaying:
                self.playStatus = PlayerStatusPlaying;
                break;
        }
    } else {
        if (_player.rate != 0) {
            if (self.playerItem.isPlaybackLikelyToKeepUp) {
                self.playStatus = PlayerStatusPlaying;
            } else {
                self.playStatus = PlayerStatusBuffering;
            }
        } else {
            self.playStatus = PlayerStatusPlaying;
        }
    }
}

avplyer有自己提供的监听进度的方法

//监听播放
    self.timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.01, NSEC_PER_SEC) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        //回调
        CGFloat second = CMTimeGetSeconds(time);
        if (self.videoProgress) {
            self.videoProgress(second);
        }
    }];

返回的值是CMTime类型,CMTime是个结构体,value表示视频一共多少帧,timeScale表示每秒钟播放几帧,所以时间(秒)=value/timeScale,也可以用CMTimeGetSeconds(time);

跳转到指定时间的方法是seekToTime,传递的值也是CMTime类型

//跳转到指定时间
-(void)jumpToTime:(NSString *)time
{
    //清除上次的seek
    [self.playerItem cancelPendingSeeks];
    //有可能会造成屏幕卡顿,所以先清除上次
    
    //先获取到时间
    CGFloat seconds = [time translateStringToSeconds];
    
    //创建CMTime
    CMTime t = CMTimeMakeWithSeconds(seconds, self.playerItem.duration.timescale);
    
    [_player seekToTime:t completionHandler:^(BOOL finished) {
    //处理跳转完之后的操作,如播放
    }];
}

视频播放完成后需要置空并且销毁监听

//停止
-(void)stop
{
    self.playerItem = nil;
    self.playStatus = PlayerStatusUnknown;
    [_player replaceCurrentItemWithPlayerItem:nil];
    _player = nil;
    [self removeObserverItems];
}

avplaylayer有个属性一定要设置,
设置填充整个屏幕。
最开始用的模拟器是iphone6,没毛病,但是换成x测适配就发现问题了,只有6的屏幕大小有视频,最后发现是视频大小就是375、667。设置这个属性,解决一切花里胡哨

_playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

你可能感兴趣的:(iosUI,ios技术点)