美文网首页
使用AVPlayer自定义播放器

使用AVPlayer自定义播放器

作者: 逆战逆的态度 | 来源:发表于2016-07-28 13:36 被阅读334次

    使用AVPlayer前需要‘“#import <AVFoundation/AVFoundation.h>”,要通过AVPlayer来播放视频需要用到以下3项:

    @property(nonatomic,strong)AVPlayer                        * player;             //播放属性
    @property(nonatomic,strong)AVPlayerItem                    * playerItem;         //播放属性
    @property(nonatomic,strong)AVPlayerLayer                   * playerLayer;        //播放属性
    

    在开发中,单纯使用AVPlayer类是无法显示视频的,要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来

    #ragma mark  - 懒加载控件 -
    - (AVPlayer *)player{
        if (!_player) {
            _player = [[AVPlayer alloc] init];
        }
        return _player;
    }
    - (AVPlayerLayer *)playerLayer{
        if (!_playerLayer) {
            _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
            _playerLayer.frame = self.bounds;
            _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
        }
        return _playerLayer;
    }
    

    把视频播放器的Layer加到视图Layer上,播放视频

     [self.layer addSublayer:self.playerLayer];
     self.playerItem = [[AVPlayerItem alloc] initWithURL:playerURL];
     [_player replaceCurrentItemWithPlayerItem:_playerItem];
     [_player play];
    

    我的自定义播放器

    MoivePlayer.h
    #import <UIKit/UIKit.h>
    #import "PlayerCommandView.h"                         //控制界面
    @interface MoivePlayer : UIView
    @property(nonatomic,strong)PlayerCommandView          * CommandView;       //控制界面
    @property(nonatomic,strong)NSURL                      * playerURL;         //视频地址
    @property(nonatomic,strong)UIViewController           * superVc;          //播放器主页面
    /*******************************************************************/
    @end
    
    MoivePlayer.m
    #import "MoivePlayer.h"
    #import <AVFoundation/AVFoundation.h>
    @interface MoivePlayer()
    @property(nonatomic,strong)AVPlayer                        * player;             //播放属性
    @property(nonatomic,strong)AVPlayerItem                    * playerItem;         //播放属性
    @property(nonatomic,strong)AVPlayerLayer                   * playerLayer;        //播放属性
    @property(nonatomic,assign)BOOL                              isFullScreen;       //是否是全屏
    @end
    @implementation MoivePlayer
    
    - (instancetype)initWithFrame:(CGRect)frame{
        if (self = [super initWithFrame:frame]) {
            [self initStep];
        }
        return self;
    }
    #pragma mark  - 懒加载控件 -
    - (AVPlayer *)player{
        if (!_player) {
            _player = [[AVPlayer alloc] init];
        }
        return _player;
    }
    
    - (AVPlayerLayer *)playerLayer{
        if (!_playerLayer) {
            _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
            _playerLayer.frame = self.bounds;
            _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
        }
        return _playerLayer;
    }
    - (PlayerCommandView *)CommandView{
        if (!_CommandView) {
            _CommandView = [[PlayerCommandView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
            _CommandView.backgroundColor = [UIColor clearColor];
        }
        return _CommandView;
    }
    
    - (void)setPlayerURL:(NSURL *)playerURL{
        self.playerItem = [[AVPlayerItem alloc] initWithURL:playerURL];
        [_player replaceCurrentItemWithPlayerItem:_playerItem];
        [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
    }
    
    #pragma mark - 初始化 -
    - (void)initStep{
        [self.layer addSublayer:self.playerLayer];
        [self addSubview:self.CommandView];
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(stup) userInfo:nil repeats:YES];
        /*------------------------------*/
        [self play];
        [self progressSlider];
        [self fullScreen];
        _isFullScreen = NO;
        /*------------------------------*/
        [self gestureAction];
    }
    #pragma mark  - Bottomview上的按钮响应方法 -
    - (void)play{
        [_player play];
        __weak typeof(self)weakself = self;
        _CommandView.playActionBlock = ^ (int n){
            if (n==1) {
                [weakself.player pause];
            }
            if (n==0) {
                [weakself.player play];
            }
        };
    }
    - (void)progressSlider{
          __weak typeof(self)weakself = self;
        _CommandView.slideActionBlock = ^(int n){
            if (n==100) {
                if (_player.status == AVPlayerStatusReadyToPlay) {
                    CGFloat total = _playerItem.duration.value/_playerItem.duration.timescale;
                    NSInteger dragedSeconds = floorf(total * _CommandView.slider.value);
                    CMTime dragedCMTime = CMTimeMake(dragedSeconds, 1);
                    [weakself.player pause];
                    [weakself.player seekToTime:dragedCMTime completionHandler:^(BOOL finished) {
                         [weakself.player play]; 
                    }];
                }
            }
        };
    }
    
    - (void)fullScreen{
        
        __weak typeof(self)weakself = self;
        
        _CommandView.fullActionBlock = ^(int n){
        
            if (n==200) {
            
                if (weakself.isFullScreen) {
                    
                    [weakself removeFromSuperview];
                
                    [weakself.superVc.view addSubview:weakself];
                    
                    [UIView animateWithDuration:0.5 animations:^{
                        
                        weakself.transform = CGAffineTransformMakeRotation(2*M_PI);
                        
                        weakself.frame = CGRectMake(0, 0, 375, 240);
                        weakself.playerLayer.frame = CGRectMake(0, 0, 375, 240);
                        weakself.CommandView.frame = CGRectMake(0, 0, 375, 240);
                        
                    } completion:^(BOOL finished) {
                        
                    }];
        
                }else{
                    
                    [weakself removeFromSuperview];
                    
                    [[UIApplication sharedApplication].keyWindow addSubview:weakself];
                    
                    [UIView animateWithDuration:0.5 animations:^{
                        
                        CGRect MovieRect = weakself.frame;
                        
                        MovieRect.size.width = [UIScreen mainScreen].bounds.size.height;
                        MovieRect.size.height = [UIScreen mainScreen].bounds.size.width;
                        weakself.frame = MovieRect;
                        weakself.playerLayer.frame = MovieRect;
                        weakself.CommandView.frame = MovieRect;
                        weakself.center = [UIApplication sharedApplication].keyWindow.center;
    
                        weakself.transform = CGAffineTransformMakeRotation(M_PI_2);
                        
                    } completion:^(BOOL finished) {
                    }];
    
                }
                
                _isFullScreen = !_isFullScreen;
            }
        };
    }
    #pragma mark - 手势相关 -
    
    - (void)gestureAction{
    
        __weak typeof(self)weakself = self;
        
        _CommandView.gestureActionBlock = ^(int n){
        
            if (n  == 1) {
                
                if (!weakself.CommandView.bottomView.hidden) {
                    
                    weakself.CommandView.bottomView.hidden = !weakself.CommandView.bottomView.hidden;
                    
                    weakself.CommandView.topView.hidden   = !weakself.CommandView.topView.hidden ;
                    
                }else{
            
                    weakself.CommandView.bottomView.hidden = !weakself.CommandView.bottomView.hidden;
                    
                    weakself.CommandView.topView.hidden   = !weakself.CommandView.topView.hidden ;
                }
            }
            
            if (n==2) {
                
                if (weakself.player.status == AVPlayerStatusReadyToPlay) {
                    
                    [weakself.player pause];
                    
                    weakself.CommandView.playBtn.selected = YES;
                    
                }else {
                    
                    [weakself.player play];
                    
                    weakself.CommandView.playBtn.selected = NO;
                }
            }
        };
    }
    
    #pragma mark - 计时器事件 -
    
    - (void)stup
    {
        if (_playerItem.duration.timescale !=0) {
            
            _CommandView.slider.maximumValue = 1;
            
             _CommandView.slider.value = CMTimeGetSeconds([_playerItem currentTime])/(_playerItem.duration.value/_playerItem.duration.timescale);
            
            NSInteger proMin = CMTimeGetSeconds([_player currentTime])/60;                                 //当前秒
            
            NSInteger proSec = (NSInteger)CMTimeGetSeconds([_player currentTime]) % 60;                    //当前分钟
            
            NSInteger durMin = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale / 60;//总秒
            
            NSInteger durSec = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale % 60;//总分钟
            
            _CommandView.currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld / %02ld:%02ld", proMin, proSec, durMin, durSec];
        }
        
        if (_player.status == AVPlayerStatusReadyToPlay) {
            
            
           // [_activity stopAnimating];
            
        }else{
            
            //[_activity startAnimating];
            
        }
    }
    
    #pragma mark - KVO键值观察 -
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
    {
        AVPlayerItem *playerItem = (AVPlayerItem *)object;
        
        if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
            
            NSTimeInterval timeInterval = [self availableDuration];                   // 计算缓冲进度
            
            CMTime duration = self.playerItem.duration;
            
            CGFloat totalDuration = CMTimeGetSeconds(duration);
            
            [_CommandView.progress setProgress:timeInterval / totalDuration animated:NO];
        }
        
        if ([playerItem status] == AVPlayerStatusReadyToPlay) {
            
           // _duration = playerItem.duration.value / playerItem.duration.timescale;  //视频总时间
        }
    }
    
    - (NSTimeInterval)availableDuration {
        
        NSArray *loadedTimeRanges = [[_player currentItem] loadedTimeRanges];
        
        CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];      // 获取缓冲区域
        
        float startSeconds = CMTimeGetSeconds(timeRange.start);
        
        float durationSeconds = CMTimeGetSeconds(timeRange.duration);
        
        NSTimeInterval result = startSeconds + durationSeconds;                       // 计算缓冲总进度
        
        return result;
    }
    
    @end
    

    下方播放器控制类

    PlayerCommandView.h
    #import <UIKit/UIKit.h>
    typedef void(^playActionBlock)(int n);
    typedef void(^slideActionBlock)(int n);
    typedef void(^fullActionBlock)(int n);
    typedef void(^gestureActionBlock)(int  n);
    
    typedef void(^panActionBlock)(int n);
    
    @interface PlayerCommandView : UIView
    
    @property(nonatomic,copy)playActionBlock    playActionBlock;
    @property(nonatomic,copy)slideActionBlock   slideActionBlock;
    @property(nonatomic,copy)fullActionBlock    fullActionBlock;
    @property(nonatomic,copy)gestureActionBlock gestureActionBlock;
    @property(nonatomic,copy)panActionBlock     panActionBlock;
    
    @property(nonatomic,strong) UIView                  * topView;               //顶部视图
    @property(nonatomic,strong) UIView                  * bottomView;            //底部视图
    
    @property(nonatomic,strong) UIProgressView      * progress;                 // 缓冲条
    @property(nonatomic,strong) UISlider            * slider;                   // 进度条
    @property(nonatomic,strong) UILabel             * currentTimeLabel;         // 当前播放时间
    @property(nonatomic,strong) UIButton            * playBtn;                  //播放、暂停按钮
    @property(nonatomic,strong) UIButton            * screenBtn;                //全屏按钮
    
    @property(nonatomic,strong) UITapGestureRecognizer  * tapGesture;           //单击手势
    @property(nonatomic,strong) UITapGestureRecognizer  * doubleTapGesture;     //双击手势
    @property(nonatomic,strong) UIPanGestureRecognizer  * panGesture;           //拖动手势
    
    @end
    
    PlayerCommandView.m
    #import "PlayerCommandView.h"
    
    @interface PlayerCommandView()
    {
        BOOL          _hasMoved;             //手势是否移动过
        BOOL          _isTouchDirection;     //是否判断出手势方向
        CGPoint       _touchBeginPoint;      //触摸开始的点
    }
    
    @end
    
    @implementation PlayerCommandView
    
    - (instancetype)initWithFrame:(CGRect)frame{
    
        if (self = [super initWithFrame:frame]) {
            
            [self initStep];
        }
    
        return self;
    }
    
    - (void)layoutSubviews{
        
        _topView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height * 0.1);
        
        _bottomView.frame = CGRectMake(0, self.frame.size.height - 40, self.frame.size.width, 40);
        
        _playBtn.frame = CGRectMake(5, 5, 30, 30);
        
        _progress.frame = CGRectMake(self.frame.size.width * 0.15, 20, self.frame.size.width * 0.5, 15);
        
        _slider.frame = CGRectMake(self.frame.size.width * 0.15, 13, self.frame.size.width * 0.5, 15);
        
        _currentTimeLabel.frame = CGRectMake(self.frame.size.width * 0.65 + 5 , 10, self.frame.size.width * 0.3, 20);
        _screenBtn.frame = CGRectMake(self.frame.size.width  - 30, 5, 30, 30);
    }
    
    #pragma mark - 懒加载 -
    
    - (UIView *)topView{
        
        if (!_topView) {
            
            _topView = [[UIView alloc] init];
            
            _topView.backgroundColor = [UIColor brownColor];
        }
        
        return _topView;
    }
    
    - (UIView *)bottomView{
    
        if (!_bottomView) {
            
            _bottomView = [[UIView alloc] init];
            
            _bottomView.backgroundColor = [UIColor brownColor];
        }
        
        return _bottomView;
    }
    
    - (UIButton *)playBtn{
    
        if (!_playBtn) {
            
            _playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            
            [_playBtn setImage:[UIImage imageNamed:@"pauseBtn"] forState:UIControlStateNormal];
            
            [_playBtn setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateSelected];
            
            [_playBtn addTarget:self action:@selector(playBtnAction:) forControlEvents:UIControlEventTouchUpInside];
        }
        
        return _playBtn;
    }
    
    - (UIProgressView *)progress{
    
        if (!_progress) {
            
            _progress = [[UIProgressView alloc] init];
        }
        
        return _progress;
    }
    
    - (UISlider *)slider{
    
        if (!_slider) {
            
            _slider = [[UISlider alloc] init];
            
            [_slider setThumbImage:[UIImage imageNamed:@"iconfont-yuan.png"] forState:UIControlStateNormal];
            
            [_slider addTarget:self action:@selector(progressSlider:) forControlEvents:UIControlEventValueChanged];
            
            _slider.minimumTrackTintColor = [UIColor colorWithRed:30 / 255.0 green:80 / 255.0 blue:100 / 255.0 alpha:1];
            
            //生成透明的图形
            
            UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);
            
            UIImage * transparentImage = UIGraphicsGetImageFromCurrentImageContext();
            
            UIGraphicsEndImageContext();
            
            [self.slider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];
            
            [self.slider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];
        }
        
        return _slider;
    }
    
    - (UILabel *)currentTimeLabel{
    
        if (!_currentTimeLabel) {
            
            _currentTimeLabel = [[UILabel alloc] init];
            
            _currentTimeLabel.textColor = [UIColor whiteColor];
            
            _currentTimeLabel.font = [UIFont systemFontOfSize:12];
            
            _currentTimeLabel.text = @"00:00/00:00";
        }
        
        return _currentTimeLabel;
    }
    
    - (UIButton *)screenBtn{
        
        if (!_screenBtn) {
            
            _screenBtn = [UIButton  buttonWithType:UIButtonTypeCustom];
            
            [_screenBtn addTarget:self action:@selector(screenBtnAction:) forControlEvents:UIControlEventTouchUpInside];
            
            [_screenBtn setImage:[UIImage imageNamed:@"icon_full"] forState:UIControlStateNormal];
        }
    
        return _screenBtn;
    }
    
    - (UITapGestureRecognizer *)tapGesture{
        
        if (!_tapGesture) {
            
            _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
            
            _tapGesture.numberOfTapsRequired = 1;
            
            _tapGesture.numberOfTouchesRequired = 1;
        }
        
        return _tapGesture;
    }
    
    - (UIPanGestureRecognizer *)panGesture{
    
        if (!_panGesture) {
            
            _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
            
            [_panGesture setMaximumNumberOfTouches:1];
            
            [_panGesture setMinimumNumberOfTouches:1];
        }
        
        return _panGesture;
    }
    
    - (UITapGestureRecognizer *)doubleTapGesture{
    
        if (!_doubleTapGesture) {
            
            _doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
            
            [_doubleTapGesture setNumberOfTapsRequired:2];
        }
        
        return _doubleTapGesture;
    }
    
    #pragma mark  - 初始化 -
    
    - (void)initStep
    {
        [self addSubview:self.topView];
        
        [self addSubview:self.bottomView];
        
        [_bottomView addSubview:self.playBtn];
        
        [_bottomView addSubview:self.progress];
        
        [_bottomView addSubview:self.slider];
        
        [_bottomView addSubview:self.currentTimeLabel];
        
        [_bottomView addSubview:self.screenBtn];
        
        [self addGestureRecognizer:self.tapGesture];
        
        [self addGestureRecognizer:self.doubleTapGesture];
        
        [self addGestureRecognizer:self.panGesture];
    }
    
    #pragma mark - 按钮的点击事件 -
    
    - (void)playBtnAction:(UIButton *)button
    {
        if (button.selected) {
            
            if (_playActionBlock) {
                
                _playActionBlock(0);
            }
            
        }else{
        
            if (_playActionBlock) {
                
                _playActionBlock(1);
            }
        }
        
        button.selected = !button.selected;
    }
    
    - (void)progressSlider:(UISlider *)slider{
        
        if (_slideActionBlock) {
            
            _slideActionBlock(100);
        }
    }
    
    - (void)screenBtnAction:(UIButton *)button{
    
        if (_fullActionBlock) {
            
            _fullActionBlock(200);
        }
    }
    
    #pragma mark - 手势相关 -
    
    - (void)tapAction:(UITapGestureRecognizer *)gesture
    {
        if (gesture.numberOfTapsRequired == 1) {
            
            if (_gestureActionBlock) {
                
                _gestureActionBlock(1);
            }
        }
    
        if (gesture.numberOfTapsRequired == 2 ) {
            
            if (_gestureActionBlock) {
                
                _gestureActionBlock(2);
            }
        }
    }
    
    - (void)panAction:(UIPanGestureRecognizer *)gesture
    {
        CGPoint touchPoint = [gesture locationInView:self];
        
        NSLog(@"%f,%f",touchPoint.x,touchPoint.y);
    }
    
    @end
    

    使用

        MoivePlayer * Player = [[MoivePlayer alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 240)];
        Player.playerURL = [NSURL URLWithString:@"http://7xnujb.com2.z0.glb.qiniucdn.com/zczs02%2Fsj2-001.mp4"];
        Player.superVc = self;
        [self.view addSubview:Player];
    

    相关文章

      网友评论

          本文标题:使用AVPlayer自定义播放器

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