首页 > 其他 > 详细

AVPlayer播放器

时间:2016-01-05 15:22:37      阅读:309      评论:0      收藏:0      [点我收藏+]

 

 

#import "AVPlayerView.h"

#import <MediaPlayer/MediaPlayer.h>

#import "JCAlertView.h"

#import "Device.h"

#import "UIView+Frame.h"

#import "MBProgressHUD.h"

 

typedef NS_ENUM(NSInteger, ViewTapState)

{

    viewTapShow,

    viewTapHide

};

 

@interface AVPlayerView () <MBProgressHUDDelegate>

{

    // 屏幕轻拍状态切换

    ViewTapState viewTapState;

}

@property(nonatomic, strong)AVPlayer *player;                   // 播放器对象

@property(nonatomic, strong)AVPlayerLayer *playerLayer;         // 播放器层

@property(nonatomic, strong)UIView *container;                  // 播放器容器

@property(nonatomic, strong)UIButton *playOrPause;              // 播放/暂停按钮

@property(nonatomic, strong)UIView *progressView;               // 播放进度

@property(nonatomic, strong)UIView *progressCache;              // 缓冲进度

@property(nonatomic, strong)UIView *progressShadow;             // 进度阴影

@property(nonatomic, strong)UIImageView *progressBar;           // 进度按钮

@property(nonatomic, strong)UILabel *currentLabel;              // 已播放时间

@property(nonatomic, strong)UILabel *durationLabel;             // 总时间

@property(nonatomic, strong)UIButton *doneBtn;                  // 播放完后屏幕显示的按钮

@property(nonatomic, strong)UIPanGestureRecognizer *barPan;     // 进度条按钮平移手势

@property(nonatomic, strong)UIPanGestureRecognizer *viewPan;    // 屏幕平移手势

@property(nonatomic, strong)NSString *movieTitle;               // 接收标题

@property(nonatomic, strong)UIView *topView;                    // 顶部视图

@property(nonatomic, strong)UIView *downView;                   // 底部视图

@property(nonatomic, strong)UILabel *movieTitleLabel;           // 视频标题

@property(nonatomic, strong)MBProgressHUD *hud;                 // loading

@property(nonatomic, strong)UIView *allUI;                      // 装载所有控件的View

@property(nonatomic, strong)UISlider *volumeSlider;             // 接收系统音量

@property(nonatomic, strong)UISlider *volume;                   // 展示系统音量的

@property(nonatomic, assign)id playBackObserver;                // 接收进度更新方法的返回值

 

@end

 

@implementation AVPlayerView

{

    CGFloat x;

    CGFloat y;

    CGFloat width;

    CGFloat height;

    NSInteger cache;                // 接收当前缓存进度

    NSInteger playCurrent;          // 接收当前播放的进度

    CGFloat timeX;                  // 时间的X偏移

    CGFloat progressBarSize;        // 进度按钮Bar大小

    CGFloat progressHeight;         // 进度条高度

    CGFloat progressBarY;           // 进按钮BarY

    CGFloat oldVolume;              // 记录上次音量

    CGFloat sumTime;                // 保存快进的值

}

 

- (void)dealloc

{

    [self removeObserverFromPlayerItem:self.player.currentItem];

    [self removeNotification];

    // 释放播放资源

    [_player replaceCurrentItemWithPlayerItem:nil];

    NSLog(@"AVPlayerView被销毁");

}

 

// 界面控件添加

- (void)addAVPlayerUI

{

    // 进度按钮Bar大小

    progressBarSize = 15 * height / 375;

    // 进度条高度

    progressHeight = 4 * height / 375;

    

    // 视频视图

    self.container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    self.container.userInteractionEnabled = NO;

    [self addSubview:_container];

    

    // 装载所有控件的View

    self.allUI = [[UIView alloc] initWithFrame:self.container.frame];

    [self addSubview:_allUI];

    

    // 顶部视图

    self.topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 50 * height / 375)];

    self.topView.backgroundColor = MLight;

    self.topView.alpha = 0.8;

    [self.allUI addSubview:_topView];

    

    // 底部视图

    self.downView = [[UIView alloc] initWithFrame:CGRectMake(0, height - 60 * height / 375, width, 60 * height / 375)];

    self.downView.backgroundColor = MLight;

    self.downView.alpha = 0.8;

    [self.allUI addSubview:_downView];

    

    // 轻拍手势添加的View

    UIView *tapView = [[UIView alloc] initWithFrame:CGRectMake(width - (width - x * 6), (height - (height - _topView.height * 1.5 - _downView.height)) / 2, width - x * 6, height - _topView.height * 1.5 - _downView.height)];

//    tapView.backgroundColor = [UIColor redColor];

    [self addSubview:tapView];

    

    // 添加轻拍手势

    UITapGestureRecognizer *viewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapAction:)];

    [tapView addGestureRecognizer:viewTap];

    

    // 添加平移手势

    self.viewPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanAction:)];

    [tapView addGestureRecognizer:_viewPan];

    

    // 视频标题

    self.movieTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(x * 2, y * 2, (width - x * 4) / 1.35, 30 * height / 375)];

    self.movieTitleLabel.text = self.movieTitle;

    self.movieTitleLabel.textColor = MWrite;

//    self.movieTitleLabel.backgroundColor = [UIColor redColor];

    self.movieTitleLabel.font = [UIFont systemFontOfSize:16 * height / 375];

    [self.allUI addSubview:_movieTitleLabel];

    

    // 播放暂停按钮

    self.playOrPause = [UIButton buttonWithType:UIButtonTypeCustom];

    self.playOrPause.frame = CGRectMake(x * 3, height - (38 * height / 375) - y, 38 * height / 375, 38 * height / 375);

    self.playOrPause.enabled = NO;

    [self.playOrPause setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

    [self.playOrPause addTarget:self action:@selector(playClick:) forControlEvents:UIControlEventTouchUpInside];

    [self.allUI addSubview:_playOrPause];

    

    // 进度背景

    self.progressShadow = [[UIView alloc] initWithFrame:CGRectMake(0, height - _downView.height, width, progressHeight)];

    self.progressShadow.backgroundColor = [UIColor colorWithRed:50 / 255.0 green:50 / 255.0 blue:50 / 255.0 alpha:1.0];

    [self.allUI addSubview:_progressShadow];

    

    // 缓冲条

    self.progressCache = [[UIView alloc] initWithFrame:CGRectMake(0, height - _downView.height, 0, progressHeight)];

    self.progressCache.backgroundColor = [UIColor colorWithRed:100 / 255.0 green:100 / 255.0 blue:100 / 255.0 alpha:1.0];

    [self.allUI addSubview:_progressCache];

    

    // 进度条

    self.progressView = [[UIView alloc] initWithFrame:CGRectMake(0, height - _downView.height, 0, progressHeight)];

    self.progressView.backgroundColor = [UIColor colorWithRed:234 / 255.0 green:128 / 255.0 blue:16 / 255.0 alpha:1.0];

    [self.allUI addSubview:_progressView];

    

    // 进按钮BarY

    progressBarY = height - _downView.height - y / 1.5;

    

    // 进度按钮

    self.progressBar = [[UIImageView alloc] initWithFrame:CGRectMake(-x / 5, progressBarY, progressBarSize, progressBarSize)];

    self.progressBar.userInteractionEnabled = YES;

    self.progressBar.image = [UIImage imageNamed:@"progressbarlight"];

    [self.allUI addSubview:_progressBar];

    

    // 添加进度按钮手势

    self.barPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(barPanAction:)];

    [self.progressBar addGestureRecognizer:_barPan];

    self.barPan.enabled = NO;

    

    // 时间x

    timeX = _downView.frame.size.width / 2.3;

    CGFloat timeY = height - _downView.height + _downView.height / 3;

    

    // 当前时间

    self.currentLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeX, timeY, 40 * height / 375, 20 * height / 375)];

    self.currentLabel.text = @"00:00";

    self.currentLabel.textColor = MWrite;

//    self.currentLabel.backgroundColor = [UIColor redColor];

    self.currentLabel.font = [UIFont systemFontOfSize:14 * height / 375];

    [self.allUI addSubview:_currentLabel];

    

    //

    UILabel *gangLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeX + _currentLabel.width, timeY, 10 * height / 375, 20 * height / 375)];

    gangLabel.text = @"/";

    gangLabel.textColor = MWrite;

    gangLabel.textAlignment = NSTextAlignmentCenter;

    gangLabel.font = [UIFont systemFontOfSize:14 * height / 375];

    [self.allUI addSubview:gangLabel];

    

    // 总时间

    self.durationLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeX + _currentLabel.width + gangLabel.width, timeY, 40 * height / 375, 20 * height / 375)];

    self.durationLabel.text = @"00:00";

    self.durationLabel.textColor = MWrite;

    self.durationLabel.font = [UIFont systemFontOfSize:14 * height / 375];

    [self.allUI addSubview:_durationLabel];

    

    // 返回退出按钮

    _backBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _backBtn.frame = CGRectMake(width - (40 * height / 375) - x * 2, timeY - y / 2, 50 * height / 375, 30 * height / 375);

    [_backBtn setTitle:@"返回" forState:UIControlStateNormal];

//    _backBtn.backgroundColor = [UIColor redColor];

    [_backBtn setTitleColor:MWrite forState:UIControlStateNormal];

    _backBtn.titleLabel.font = [UIFont systemFontOfSize:17 * height / 375];

    [self.allUI addSubview:_backBtn];

    

    // 重播按钮

    self.doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    self.doneBtn.frame = CGRectMake((width - 50 * width / 375) / 2, (height - 50 * width / 375) / 2, 50 * width / 375, 50 * width / 375);

    self.doneBtn.hidden = YES;

    [self.doneBtn setImage:[UIImage imageNamed:@"again"] forState:UIControlStateNormal];

    [self.doneBtn addTarget:self action:@selector(doneBtnAction:) forControlEvents:UIControlEventTouchUpInside];

    [self addSubview:_doneBtn];

    

    // 收藏按钮

    _collectBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _collectBtn.frame = CGRectMake(width - _backBtn.width - (24 * height / 375) * 2.5, timeY - y / 3, 24 * height / 375, 24 * height / 375);

    [_collectBtn setImage:[UIImage imageNamed:@"collectBtn1"] forState:UIControlStateNormal];

    [_collectBtn setImage:[UIImage imageNamed:@"collectBtn2"] forState:UIControlStateSelected];

    [self.allUI addSubview:_collectBtn];

    

    // 分享按钮

    _shareBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _shareBtn.frame = CGRectMake(width - _backBtn.width - _collectBtn.width - (24 * height / 375) * 4, timeY - y / 3, 24 * height / 375, 24 * height / 375);

    [_shareBtn setImage:[UIImage imageNamed:@"shareBtn"] forState:UIControlStateNormal];

    [self.allUI addSubview:_shareBtn];

    

    // 列表按钮

    _tableBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _tableBtn.frame = CGRectMake(width - (24 * height / 375) - x * 2, y * 2, 24 * height / 375, 24 * height / 375);

    [_tableBtn setImage:[UIImage imageNamed:@"tableBtn"] forState:UIControlStateNormal];

    [self.allUI addSubview:_tableBtn];

    

    // 静音按钮

    _muteBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _muteBtn.frame = CGRectMake(width - _tableBtn.width - (24 * height / 375) * 3.5, y * 2, 24 * height / 375, 24 * height / 375);

    [_muteBtn setImage:[UIImage imageNamed:@"volume1"] forState:UIControlStateNormal];

    [_muteBtn setImage:[UIImage imageNamed:@"volume2"] forState:UIControlStateSelected];

    [_muteBtn addTarget:self action:@selector(muteBtnAction:) forControlEvents:UIControlEventTouchUpInside];

    [self.allUI addSubview:_muteBtn];

    

    // 举报按钮

    _reportBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    _reportBtn.frame = CGRectMake(width - _muteBtn.width - _tableBtn.width - (24 * height / 375) * 5, y * 2, 24 * height / 375, 24 * height / 375);

    [_reportBtn setImage:[UIImage imageNamed:@"reportBtn"] forState:UIControlStateNormal];

    [_reportBtn addTarget:self action:@selector(reportBtnAction:) forControlEvents:UIControlEventTouchUpInside];

    [self.allUI addSubview:_reportBtn];

    

    // 创建音量展示控件

    self.volume = [[UISlider alloc] initWithFrame:CGRectMake(0, height - _downView.height * 3.5, height / 2, 10)];

    self.volume.transform = CGAffineTransformMakeRotation(M_PI * 1.5);

    self.volume.center = CGPointMake(30, height / 2);

    [self.volume setMinimumTrackTintColor:[UIColor colorWithRed:234 / 255.0 green:128 / 255.0 blue:16 / 255.0 alpha:1.0]];

    [self.volume addTarget:self action:@selector(volumeAction:) forControlEvents:UIControlEventValueChanged];

    [self.volume setThumbImage:[UIImage imageNamed:@"progressVolume"] forState:UIControlStateNormal];

    

    // 控制系统音量

    // 我们给一个frame超出系统可视范围 从而达到隐藏系统自己音量的控件

    MPVolumeView *volumeXT = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, 0, 30, 30)];

    for (UIView *view in volumeXT.subviews)

    {

        if ([view isKindOfClass:[UISlider class]])

        {

            // 接收系统音量

            self.volumeSlider = (UISlider *)view;

            // 接收到控件之后 要给我们系统的控件赋一个初始值

            self.volume.value = self.volumeSlider.value;

        }

    }

    // 一定要添加 不然添加声音的是时候 还是会出现 设置隐藏属性也是可以出现的

    [self addSubview:volumeXT];

    [self addSubview:_volume];

    

    // loading

    self.hud = [[MBProgressHUD alloc] initWithView:self];

    [tapView addSubview:_hud];

    self.hud.delegate = self;

    self.hud.labelText = @"请稍后...";

    self.hud.labelFont = [UIFont systemFontOfSize:14 * height / 375];

    // 显示转菊花

    [self.hud show:YES];

}

 

// 自定义初始化实现

- (instancetype)initWithFrame:(CGRect)frame movieUrl:(NSString *)movieUrl movieTitle:(NSString *)movieTitle

{

    self = [super initWithFrame:frame];

    if (self)

    {

        width = frame.size.width;

        height = frame.size.height;

        

        x = 5 * width / 375;

        y = 5 * width / 375;

        

        // 初始化时间

        sumTime = 0;

        

        // 初始化屏幕状态

        viewTapState = viewTapHide;

 

        // 接收标题

        self.movieTitle = movieTitle;

        

        // 界面控件添加

        [self addAVPlayerUI];

        

        // 创建播放器对象

        [self createVideoWithMovieUrl:movieUrl];

        

        // 开始播放

        [self startMovie];

 

        

    }

    return self;

}

 

// 创建播放器对象

- (void)createVideoWithMovieUrl:(NSString *)movieUrl

{

    NSString *urlStr = [movieUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:urlStr]];

    _player = [AVPlayer playerWithPlayerItem:playerItem];

    [self addProgressObserver];

    [self addObserverToPlayerItem:playerItem];

    [self addNotification];

    

    //创建播放器层

    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];

    self.playerLayer.frame = self.container.frame;

    self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;//视频填充模式

    [self.container.layer addSublayer:_playerLayer];

}

 

// 开始播放

- (void)startMovie

{

    [self.player play];

}

 

// 停止播放

- (void)stopMovie

{

    [self.player pause];

}

 

// 停止播放 给外部销毁使用

- (void)stopMovieAndRemove

{

    [self stopMovie];

    // 销毁player的进度更新方法 否则会导致无法销毁视图

    [self removePlayerTimeObserver];

    // 不需要在给player滞空了,否则引用计数为-1 就奔溃了

}

 

// 销毁player的进度更新方法 否则会导致无法销毁视图

- (void)removePlayerTimeObserver

{

    if (_playBackObserver)

    {

        [self.player removeTimeObserver:_playBackObserver];

    }

}

 

// 举报按钮方法

- (void)reportBtnAction:(UIButton *)reportBtn

{

    // 暂停后弹出提示

    [self stopMovie];

    [self.playOrPause setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateNormal];

    [JCAlertView showTwoButtonsWithTitle:@"温馨提示" Message:@"是否确定举报该视频?" ButtonType:JCAlertViewButtonTypeCancel ButtonTitle:@"取消" Click:^{

        // 点击确定后恢复播放

        [self startMovie];

        [self.playOrPause setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

    } ButtonType:JCAlertViewButtonTypeDefault ButtonTitle:@"确定" Click:^{

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            [JCAlertView showOneButtonWithTitle:@"温馨提示" Message:@"举报成功" ButtonType:JCAlertViewButtonTypeDefault ButtonTitle:@"确定" Click:^{

                // 点击确定后恢复播放

                [self startMovie];

                [self.playOrPause setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

            }];

        });

    }];

}

 

// 音量方法

- (void)volumeAction:(UISlider *)volume

{

    // 更改系统的音量

    self.volumeSlider.value = volume.value;

    oldVolume = volume.value;

}

 

// 静音按钮方法

- (void)muteBtnAction:(UIButton *)muteBtn

{

    muteBtn.selected = !muteBtn.selected;

    if (muteBtn.selected)

    {

        self.volume.value = 0;

    }

    else

    {

        self.volume.value = oldVolume;

    }

    self.volumeSlider.value = self.volume.value;

}

 

// 轻拍屏幕方法

- (void)viewTapAction:(UITapGestureRecognizer *)viewTap

{

    // 如果当前为显示状态 那么就隐藏顶部和底部View以及控件

    if (viewTapState == viewTapShow)

    {

        self.volume.hidden = YES;

        self.allUI.hidden = YES;

        viewTapState = viewTapHide;

    }

    else

    {

        self.volume.alpha = 1;

        self.allUI.alpha = 1;

        self.allUI.hidden = NO;

        self.volume.hidden = NO;

        viewTapState = viewTapShow;

    }

}

 

// 重播按钮触发

- (void)doneBtnAction:(UIButton *)doneBtn

{

    // 添加layer

    [self.container.layer addSublayer:_playerLayer];

    self.progressBar.image = [UIImage imageNamed:@"progressbar"];

    self.barPan.enabled = YES;

    self.playOrPause.enabled = YES;

    // 图标更换

    [self.playOrPause setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

    // 重播按钮隐藏

    self.doneBtn.hidden = YES;

    // 重播

    [self.player seekToTime:CMTimeMake(0, 1) completionHandler:^(BOOL finished) {

        [self startMovie];

    }];

}

 

// 屏幕平移手势方法

- (void)viewPanAction:(UIPanGestureRecognizer *)viewPan

{

    // 获取手势上边的点

    CGPoint touch = [viewPan velocityInView:self];

    if (viewPan.state == UIGestureRecognizerStateBegan)

    {

        // 当前frame宽度 * 总时长 / frame长度 = 当前时间

        CGFloat duration = CMTimeGetSeconds([self.player.currentItem duration]);

        sumTime = _progressView.frame.size.width * duration / _progressShadow.frame.size.width;

    }

    // 平移中

    else if (viewPan.state == UIGestureRecognizerStateChanged)

    {

        sumTime += touch.x / 304;

    }

    // 结束触摸

    else if (viewPan.state == UIGestureRecognizerStateEnded)

    {

        // 设置时间

        [self.player seekToTime:CMTimeMake(sumTime, 1.0) completionHandler:^(BOOL finished) {

            // 滞空 否则越来越多

            sumTime = 0;

        }];

    }

}

 

#warning 拖进度

// 进度按钮平移手势触发方法

- (void)barPanAction:(UIPanGestureRecognizer *)barPan

{

    // 获取手势上边的点

    CGPoint touch = [barPan locationInView:self];

    // 范围判断

    if (touch.x < -x / 4)

    {

        touch.x = -x / 4;

    }

    else if (touch.x > _progressShadow.frame.size.width - x * 1.1)

    {

        touch.x = _progressShadow.frame.size.width - x * 1.1;

    }

    //    NSLog(@"%f",touch.x);

    self.progressBar.frame = CGRectMake(touch.x - x / 2, progressBarY, progressBarSize, progressBarSize);

 

    self.progressView.frame = CGRectMake(0, height - _downView.frame.size.height, _progressBar.frame.origin.x + x / 2, progressHeight);

    

    // 当正在改变的时候

    if (barPan.state == UIGestureRecognizerStateChanged)

    {

        // 获得当前播放时间

        float current = CMTimeGetSeconds([self.player currentTime]);

        

        // 更新时间

        self.currentLabel.text = [AVPlayerView durationStringWithTime:(NSInteger)current];

        

        // 当前frame宽度 * 总时长 / frame长度 = 当前时间

        CGFloat duration = CMTimeGetSeconds([self.player.currentItem duration]);

        

        int time = _progressView.frame.size.width * duration / _progressShadow.frame.size.width + x * 1.2;

        

        // 设置时间

        [self.player seekToTime:CMTimeMake(time, 1.0) completionHandler:^(BOOL finished) {

            

        }];

    }

}

 

#pragma mark - 添加播放器通知

- (void)addNotification

{

    //AVPlayerItem添加播放完成通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

    

    // 监听网络不好的时候或者播放到缓存进度的时候

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStalled:) name:AVPlayerItemPlaybackStalledNotification object:self.player.currentItem];

}

 

- (void)removeNotification

{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

// 监听网络不好的时候或者播放到缓存进度的时候

- (void)playbackStalled:(NSNotification *)play

{

    NSLog(@"网络不怎么好");

    // 图标更换

    [self.playOrPause setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateNormal];

    // 添加定时器

    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(playCache:) userInfo:nil repeats:YES];

 

    // 显示转菊花

    [self.hud show:YES];

}

 

// 1秒检测一次上次暂停进度 当前最新的缓存进度的差值

- (void)playCache:(NSTimer *)time

{

    // 获得当前播放进度值

    playCurrent = (NSInteger)CMTimeGetSeconds([self.player currentTime]);

    NSLog(@"current == %ld",playCurrent);

    

    // 当前缓存进度 大于 当前播放进度

    if (cache > playCurrent + 1)

    {

        // 隐藏转菊花

        [self.hud hide:YES];

        

        // 图标更换

        [self.playOrPause setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

        [self startMovie];

        // 移除定时器

        [time invalidate];

    }

}

 

#pragma mark - 播放完成通知

- (void)playbackFinished:(NSNotification *)notification

{

    NSLog(@"视频播放完成.");

    

    // layer层上移除

    [self.playerLayer removeFromSuperlayer];

    

    // 当前时间滞空

    self.currentLabel.text = @"00:00";

    

    // 进度滞空

    self.progressView.frame = CGRectMake(0, height - _downView.frame.size.height, 0, progressHeight);

    

    // 图标更换

    [self.playOrPause setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateNormal];

    

    // bar归位

    self.progressBar.frame = CGRectMake(-x / 5, progressBarY, progressBarSize, progressBarSize);

    

    // 禁止点击小播放按钮

    self.playOrPause.enabled = NO;

    

    // 关闭进度条平移手势交互

    self.barPan.enabled = NO;

    

    self.progressBar.image = [UIImage imageNamed:@"progressbarlight"];

    

    // 重播按钮出现

    self.doneBtn.hidden = NO;

}

 

#pragma mark - 监控 给播放器添加进度更新

- (void)addProgressObserver

{

    AVPlayerItem *playerItem = self.player.currentItem;

    UIView *progressView = self.progressView;

    UIView *progressShadow = self.progressShadow;

    UILabel *currentLabel = self.currentLabel;

    UILabel *durationLabel = self.durationLabel;

    UIImageView *progressBar = self.progressBar;

    UIPanGestureRecognizer *barPan = self.barPan;

    UIPanGestureRecognizer *viewPan = self.viewPan;

    

    //这里设置每秒执行一次

    self.playBackObserver = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

        // 获取当前播放多少秒

        float current = CMTimeGetSeconds(time);

        // 获取总时长

        float duration = CMTimeGetSeconds([playerItem duration]);

        

        if (current)

        {

            // 当手势在改变

            if (barPan.state == UIGestureRecognizerStateChanged || viewPan.state == UIGestureRecognizerStateChanged)

            {

                return;

            }

            

            // 更新当前播放进度 bar

            progressView.frame = CGRectMake(0, height - _downView.frame.size.height, current * (progressShadow.frame.size.width - x * 0.9) / duration, progressHeight - 0);

            if (progressView.frame.size.width > x / 4)

            {

                progressBar.frame = CGRectMake(progressView.frame.size.width - x / 2, progressBarY - 0, progressBarSize - 0, progressBarSize - 0);

            }

            

            // 更新时间

            currentLabel.text = [AVPlayerView durationStringWithTime:(NSInteger)current];

            durationLabel.text = [AVPlayerView durationStringWithTime:(NSInteger)duration];

        }

    }];

}

 

#pragma mark - 当前时间换算

+ (NSString *)durationStringWithTime:(NSInteger)time

{

    // 获取分

    NSString *m = [NSString stringWithFormat:@"%02ld",time / 60];

    // 获取秒

    NSString *s = [NSString stringWithFormat:@"%02ld",time % 60];

    

    return [NSString stringWithFormat:@"%@:%@",m,s];

}

 

#pragma mark - AVPlayerItem添加监控 playerItem AVPlayerItem对象

- (void)addObserverToPlayerItem:(AVPlayerItem *)playerItem

{

    // 监控状态属性,注意AVPlayer也有一个status属性,通过监控它的status也可以获得播放状态

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

    // 监控网络加载情况属性

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

}

 

#pragma mark - 移除

- (void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem

{

    [playerItem removeObserver:self forKeyPath:@"status"];

    [playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];

}

 

/**

 *  通过KVO监控播放器状态

 *

 *  @param keyPath 监控属性

 *  @param object  监视器

 *  @param change  状态改变

 *  @param context 上下文

 */

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

    AVPlayerItem *playerItem = object;

    // 获取总时长

    float duration = CMTimeGetSeconds([playerItem duration]);

    if ([keyPath isEqualToString:@"status"])

    {

        AVPlayerStatus status = [[change objectForKey:@"new"] intValue];

        if(status == AVPlayerStatusReadyToPlay)

        {

            // 获取系统音量

            self.volume.value = self.volumeSlider.value;

            oldVolume = self.volume.value;

            

            // 动画隐藏控件

            [UIView animateWithDuration:0.5 animations:^{

                self.allUI.alpha = 0;

                self.volume.alpha = 0;

            }];

            

            // 隐藏转菊花

            [self.hud hide:YES];

            

            self.playOrPause.enabled = YES;

            // 打开进度条平移手势交互

            self.barPan.enabled = YES;

            self.progressBar.image = [UIImage imageNamed:@"progressbar"];

            NSLog(@"正在播放...,视频总长度:%.2f",duration);

        }

    }

    else if([keyPath isEqualToString:@"loadedTimeRanges"])

    {

        NSArray *array = playerItem.loadedTimeRanges;

        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围

        float startSeconds = CMTimeGetSeconds(timeRange.start);

        float durationSeconds = CMTimeGetSeconds(timeRange.duration);

        NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度

        // 接收当前缓存值

        cache = (NSInteger)totalBuffer;

        NSLog(@"cache == %ld",cache);

        //        NSLog(@"共缓冲:%.2f",totalBuffer);

        [UIView animateWithDuration:0.3 animations:^{

            // 更新当前缓存条

            self.progressCache.frame = CGRectMake(0, height - _downView.frame.size.height, totalBuffer * _progressShadow.frame.size.width / duration, progressHeight);

        }];

    }

}

 

#pragma mark - UI事件 点击播放/暂停按钮

- (void)playClick:(UIButton *)button

{

    //    AVPlayerItemDidPlayToEndTimeNotification

    //AVPlayerItem *playerItem = self.player.currentItem;

    if(self.player.rate == 0)

    {

        //播放

        [button setImage:[UIImage imageNamed:@"pasueBtn"] forState:UIControlStateNormal];

        [self.player play];

    }

    else if(self.player.rate == 1)

    {

        //暂停

        [self.player pause];

        [button setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateNormal];

    }

}

 

 

///**

// *  切换选集,这里使用按钮的tag代表视频名称

// *

// *  @param sender 点击按钮对象

// */

//- (void)navigationButtonClick:(UIButton *)sender {

//    [self removeNotification];

//    [self removeObserverFromPlayerItem:self.player.currentItem];

//    AVPlayerItem *playerItem=[self getPlayItem:sender.tag];

//    [self addObserverToPlayerItem:playerItem];

//    //切换视频

//    [self.player replaceCurrentItemWithPlayerItem:playerItem];

//    [self addNotification];

//}

 

 

 

@end

AVPlayer播放器

原文:http://www.cnblogs.com/kzw6412/p/5102123.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!