// // VideoHelperViewController.m // Lighting // // Created by 曹云霄 on 2016/11/25. // Copyright © 2016年 上海勾芒科技有限公司. All rights reserved. // #import "VideoHelperViewController.h" @interface VideoHelperViewController ()<UIDocumentInteractionControllerDelegate> /** 导航栏、工具类是否隐藏 */ @property (nonatomic,assign) BOOL toolNaviViewIsHide; @end @implementation VideoHelperViewController - (void)viewDidLoad { [super viewDidLoad]; [self uiConfigAction]; } #pragma mark - UI - (void)uiConfigAction { self.videoNavigationView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; self.videoToolView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideOrShowNavigationBarAndToolBar)]]; } #pragma mark - - (void)judgeVideoOrPPT { NSURL *movieURL = [NSURL URLWithString:self.learningItem.attachment.fileUrl]; NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:movieURL options:opts]; // 初始化视频媒体文件 NSInteger second = 0; second = urlAsset.duration.value / urlAsset.duration.timescale; // 获取视频总时长,单位秒 //NSLog(@"movie duration : %d", second); NSLog(@"%ld",second); } #pragma mark - 播放地址 - (void)setLearningItem:(CustomStudyEntity *)learningItem { _learningItem = learningItem; [self resetPlayer]; if (_learningItem) { [self setUpAVPlayer]; [self addAVPlayerKVO]; [self addProgressObserver]; } } #pragma mark - SetUp AVPlayer - (void)setUpAVPlayer { VIResourceLoaderManager *resourceLoaderManager = [VIResourceLoaderManager new]; self.resourceLoaderManager = resourceLoaderManager; self.playerItem = [resourceLoaderManager playerItemWithURL:[NSURL URLWithString:self.learningItem.attachment.fileUrl]]; VICacheConfiguration *configuration = [VICacheManager cacheConfigurationForURL:[NSURL URLWithString:self.learningItem.attachment.fileUrl]]; if (configuration.progress >= 1.0) { NSLog(@"缓存完成"); } [XBLoadingView showHUDViewWithDefault]; self.customPlayer = [[AVPlayer alloc] initWithPlayerItem:self.playerItem]; self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.customPlayer]; self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; self.playerLayer.frame = CGRectMake(0, 0, ScreenWidth*2/3, ScreenHeight/2); [self.view.layer insertSublayer:self.playerLayer atIndex:0]; //设置静音模式播放声音 AVAudioSession * session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; } #pragma mark - AVPlayer KVO - (void)addAVPlayerKVO { //播放状态属性 [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; //监控网络加载情况属性 [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; //给AVPlayerItem添加播放完成通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; } #pragma mark -KVO回调 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"status"]) {//播放状态 NSInteger status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; switch (status) { case AVPlayerStatusFailed: self.bufferProgressView.progress = ZERO; self.playButton.selected = YES; [XBLoadingView showHUDViewWithText:@"播放失败"]; break; case AVPlayerStatusReadyToPlay://正在播放 [XBLoadingView hideHUDViewWithDefault]; self.playItemTotalTimeLabel.text = [NSString stringWithFormat:@"/ %@",[self convertTime:CMTimeGetSeconds(self.playerItem.duration)]]; self.playButton.selected = NO; break; default: break; } }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){//缓冲 NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度 if (timeInterval > self.getCurrentPlayingTime+5){ // 缓存 大于 播放 当前时长+5 [self.customPlayer play]; } } } #pragma mark - 返回当前视频播放时长 - (double)getCurrentPlayingTime{ return self.customPlayer.currentTime.value/self.customPlayer.currentTime.timescale; } #pragma mark - 返回当前视频缓存时长 - (NSTimeInterval)availableDuration{ NSArray *loadedTimeRanges = [[self.customPlayer currentItem] loadedTimeRanges]; CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域 float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度 return result; } #pragma mark -播放进度条更新 -(void)addProgressObserver { WS(weakSelf); AVPlayerItem *playerItem = self.customPlayer.currentItem; self.avplayerServer = [self.customPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time){ float current = CMTimeGetSeconds(time); float total = CMTimeGetSeconds(playerItem.duration); //更新进度条 float progress = current/total; weakSelf.bufferProgressView.progress = progress; //更新播放时间 CMTime ctime = weakSelf.customPlayer.currentTime; weakSelf.playingTimeLabel.text = [weakSelf convertTime:ctime.value/ctime.timescale]; }]; } #pragma mark - 隐藏(显示)状态栏、工具栏 - (void)hideOrShowNavigationBarAndToolBar { WS(weakSelf); [UIView animateWithDuration:0.4 animations:^{ weakSelf.videoNavigationView.alpha = weakSelf.toolNaviViewIsHide?1:0; weakSelf.videoToolView.alpha = weakSelf.toolNaviViewIsHide?1:0; }completion:^(BOOL finished) { weakSelf.toolNaviViewIsHide = !weakSelf.toolNaviViewIsHide; }]; } #pragma mark -计算时间 - (NSString *)convertTime:(CGFloat)second { NSDate *date = [NSDate dateWithTimeIntervalSince1970:second]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; if (second/3600 >= 1) { [formatter setDateFormat:@"HH:mm:ss"]; } else { [formatter setDateFormat:@"mm:ss"]; } NSString *showtimeNew = [formatter stringFromDate:date]; return showtimeNew; } #pragma mark - 播放完成 - (void)playFinish { [self.customPlayer seekToTime:kCMTimeZero]; self.playButton.selected = YES; if ([self.delegate respondsToSelector:@selector(videoPlayFinish:)]) { [self.delegate videoPlayFinish:self.learningItem]; } } #pragma mark - 播放、暂停 - (IBAction)playOrPauseButtonClickAction:(UIButton *)sender { sender.selected = !sender.selected; if (sender.selected) { [self.customPlayer pause]; }else { [self.customPlayer play]; } } #pragma mark - 退出播放 - (IBAction)exitPlayControllerButtonClick:(UIButton *)sender { [self.customPlayer pause]; [self.navigationController popViewControllerAnimated:YES]; } #pragma mark - 后退5秒 - (IBAction)backFiveSecondButtnClick:(UIButton *)sender { [self.customPlayer seekToTime:CMTimeMake(5, 1)]; } #pragma mark - 放大缩小按钮 - (IBAction)zoomButtonClick:(UIButton *)sender { sender.selected = !sender.selected; if (self.zoomButtonClickBlock) { self.zoomButtonClickBlock(sender.selected); } } #pragma mark - 页面消失后释放播放器 - (void)viewDidDisappear:(BOOL)animated { [self.customPlayer pause]; [self.customPlayer.currentItem cancelPendingSeeks]; [self.customPlayer.currentItem.asset cancelLoading]; } #pragma mark - 重置播放器 - (void)resetPlayer { [self.customPlayer pause]; [self.customPlayer seekToTime:kCMTimeZero]; self.playButton.selected = YES; self.bufferProgressView.progress = 0; self.playingTimeLabel.text = @"00:00"; self.customPlayer = nil; [self.playerLayer removeFromSuperlayer]; } #pragma mark - 释放KVO - (void)dealloc { [self.playerItem removeObserver:self forKeyPath:@"status"]; [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"]; [self.customPlayer removeTimeObserver:self.avplayerServer]; } @end