#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
原文:http://www.cnblogs.com/kzw6412/p/5102123.html