iOS 音视频iOS音视频iOS 移动端开发

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

2017-02-28  本文已影响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。

上一篇下一篇

猜你喜欢

热点阅读