美文网首页iOS 音视频iOS音视频iOS 移动端开发
使用AVPlayer自定义支持全屏的播放器(三)

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

作者: 季末微夏 | 来源:发表于2017-02-28 14:12 被阅读1735次

前言

前段时间封装了一个视频播放器使用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。

相关文章

网友评论

  • 菜先生:为什么要添加到window上?
    季末微夏:@菜先生 放在最上层,防止被其他遮挡住
  • 呆木大人: pop 手势导致 AVPlayer 播放卡顿 , 解决了吗
    呆木大人:@季末微夏 我能说我看不懂吗,大神
    季末微夏:@呆木大人 拉取1.0.7版本的代码,最近修复了很多bug
  • iOS_沧海一笑:楼主你好, 我想问一下,我用了你这个框架,用的挺好的,之前一直没有什么问题,现在出现了一个问题,视频都已经缓冲好了,但就是一直不播放。这个是什么问题呢,现在急需解决?请求楼主赐教!!谢谢了!!
    d208f107c888:不能播放 一直提示加载失败
    iOS_沧海一笑:@枫叶流转 调用了,之前还播放着好好的,现在不知道怎么回事了?
    季末微夏:你调用播放没有?
  • 卟师:我能转载分享吗? 我会标注上作者和出处的
    季末微夏:@卟师 可以
  • 95a94c3ba4e8:封装得很好,用起来很方便
  • 0b25d76d610a:兄弟,你的demo,视频切换到横屏,通过苹果声音按键来增加声音的时候,调节声音的界面并没有切换到横屏
    季末微夏:@星辰_ffe5 最近重构了一下,已经解决音量图标问题
  • 蔡胜波:支持一下
  • 超chaoZc:不错不错:+1:

本文标题:使用AVPlayer自定义支持全屏的播放器(三)

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