使用AVPlayer自定义支持全屏的播放器(三)

前言

前段时间封装了一个视频播放器使用AVPlayer自定义支持全屏的播放器(二),还有很多没有完善的功能,最近花时间完善了一下,修复了很多bug,也增加了一些功能,最主要的还是使用Masonry重构了播放器的工具条,将工具条单独封装出来,方便大家自己修改。本篇文章主要讲新增加的功能。

新增功能

新增加了视频卡顿监听,加载视频失败处理,增加了视频拉伸方式。

1.视频卡顿监听

很多时候播放视频并不是那么理想的网络环境,这时候为了优化用户体验,我们就需要增加卡顿时候的逻辑,主要思路是增加一个播放器的状态属性,再通过监听播放器的status,loadedTimeRanges,playbackBufferEmpty,playbackLikelyToKeepUp这几个属性来调用状态属性的set方法,在set方法中集中处理各种不同状态。这里主要借鉴参考了ZFPlayer

监听代码

#pragma mark - 监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"status"]) {
        
        if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
            self.state = CLPlayerStatePlaying;
        }
        else if (self.player.currentItem.status == AVPlayerItemStatusFailed) {
            self.state = CLPlayerStateFailed;
        }
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        
        // 计算缓冲进度
        NSTimeInterval timeInterval = [self availableDuration];
        CMTime duration             = self.playerItem.duration;
        CGFloat totalDuration       = CMTimeGetSeconds(duration);
        [self.maskView.progress setProgress:timeInterval / totalDuration animated:NO];

    } else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
        
        // 当缓冲是空的时候
        if (self.playerItem.playbackBufferEmpty) {
            self.state = CLPlayerStateBuffering;
            [self bufferingSomeSecond];
        }
        
    } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
        
        // 当缓冲好的时候
        if (self.playerItem.playbackLikelyToKeepUp && self.state == CLPlayerStateBuffering){
            self.state = CLPlayerStatePlaying;
        }
        
    }
}

状态的set方法

- (void)setState:(CLPlayerState)state{
    _state = state;
    if (state == CLPlayerStateBuffering) {
        [self.maskView.activity startAnimating];
    }else if (state == CLPlayerStateFailed){
        [self.maskView.activity stopAnimating];
        NSLog(@"加载失败");
        self.maskView.failButton.hidden = NO;
    }else{
        [self.maskView.activity stopAnimating];
        [self playVideo];
    }
}

2.视频加载失败处理

和卡顿类似,也是通过监听视频播放状态来实现,在视频加载失败的时候显示一个提示按钮,点击按钮重新加载视频url即可。

加载失败按钮点击事件

#pragma mark - 播放失败按钮点击事件
-(void)cl_failButtonAction:(UIButton *)button{
     //重置url
    [self setUrl:_url];
    //刷新UI
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

3.视频拉伸方式

AVPlayer的API中就有一个视频拉伸方式,这里只是给了一个初始值简单封装了一下。

封装后的拉伸方式

typedef NS_ENUM(NSInteger,VideoFillMode){
    Resize = 0,          //拉伸占满整个播放器,不按原比例拉伸
    ResizeAspect,        //按原视频比例显示,是竖屏的就显示出竖屏的,两边留黑
    ResizeAspectFill,    //按照原比例拉伸占满整个播放器,但视频内容超出部分会被剪切
};

播放器效果图

效果图1.gif
效果图2.gif
效果图3.gif

总结

其实主要的还是完善了很多细节,修改了许多bug,具体请在github下载CLPlayer , 如果喜欢,欢迎star。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,194评论 4 61
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,062评论 25 709
  • 一 雨打青石板,淅沥沥,滴滴答,听一曲梵音,将浮尘关在窗外。 阳台上的花一大部分属于菊科,没到菊开的季节,可能是这...
    芳心伴暖阅读 2,435评论 0 5
  • 01 让自己过得不好,这是最让人遗憾的不幸。幸福需要充分动用“五感”去享受它。 我们说过有信仰的人更容易感受到幸福...
    鹿雯立love阅读 7,106评论 1 1