代码地址以下:
http://www.demodashi.com/demo/11168.htmlhtml
//建立播放器 url = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:url]]; self.avPlayer = player;
- (void)createDisplay{ // 显示图像的 _videoLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; //锚点的坐标 _videoLayer.position = CGPointMake(KPLAYVIEWWIDTH/2, KPLAYVIEWHEIGHT/2); _videoLayer.bounds = CGRectMake(0, 0, KPLAYVIEWWIDTH, KPLAYVIEWHEIGHT); // 锚点,值只能是0,1之间 _videoLayer.anchorPoint = CGPointMake(0.5, 0.5); // AVLayerVideoGravityResizeAspect 按比例压缩,视频不会超出Layer的范围(默认) // AVLayerVideoGravityResizeAspectFill 按比例填充Layer,不会有黑边 // AVLayerVideoGravityResize 填充整个Layer,视频会变形 // 视频内容拉伸的选项 _videoLayer.videoGravity = AVLayerVideoGravityResizeAspect; // //播放时,视频实际占的区域 // NSLog(@"%@", NSStringFromCGRect(videoLayer.videoRect)); //Layer只能添加到Layer上面 [self.displayView.layer addSublayer:_videoLayer]; }
主要代码以下:网络
//监测屏幕旋转 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; //添加AVPlayerItem播放结束通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayer.currentItem]; //添加AVPlayerItem开始缓冲通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bufferStart:) name:AVPlayerItemPlaybackStalledNotification object:self.avPlayer.currentItem]; //KOV监控 播放器进度更新 - (void)addObserverForAVPlayer { AVPlayerItem *playerItem = self.avPlayer.currentItem; // 给AVPlayer添加观察者 必须实现 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; //监控播放速率 [self.avPlayer addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:nil]; //监控状态属性(AVPlayer也有一个status属性,经过监控它的status也能够得到播放状态) [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; //监控网络加载缓冲状况属性 [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; //监控是否可播放 [playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; //播放进度观察者 //设置每0.1秒执行一次 __weak GOVVideoView *weakSelf = self; _playerTimeObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 10.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { if (weakSelf.dragSlider) { return ; } CGFloat current = CMTimeGetSeconds(time); weakSelf.current = current; CMTime totalTime = weakSelf.avPlayer.currentItem.duration; CGFloat total = CMTimeGetSeconds(totalTime); weakSelf.total = total; weakSelf.slider.value = current/total; weakSelf.currentTimeLabel.text = [weakSelf timeFormatted:current]; weakSelf.totalTimeLabel.text = [NSString stringWithFormat:@"/%@",[weakSelf timeFormatted:total]] ; }]; } //经过KVO监控回调 //keyPath 监控属性 object 监视器 change 状态改变 context 上下文 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"loadedTimeRanges"]) { //监控网络加载状况属性 NSArray *array = self.avPlayer.currentItem.loadedTimeRanges; //本次缓冲时间范围 CMTimeRange timeRange = [array.firstObject CMTimeRangeValue]; CGFloat startSeconds = CMTimeGetSeconds(timeRange.start); CGFloat durationSeconds = CMTimeGetSeconds(timeRange.duration); //现有缓冲总长度 CGFloat totalBuffer = startSeconds + durationSeconds; //视频总时长 CMTime totalTime = self.avPlayer.currentItem.duration; CGFloat total = CMTimeGetSeconds(totalTime); if (totalBuffer/total <= 1.0 ) { [self.progressView setProgress:totalBuffer/total animated:YES]; } }else if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]){ if (self.avPlayer.currentItem.playbackLikelyToKeepUp == YES) { if (_activityView != nil) { [self.activityView startAnimating]; [self.activityView removeFromSuperview]; _activityView = nil; } } }else if ([keyPath isEqualToString:@"status"]){ //监控状态属性 AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; switch ((status)) { case AVPlayerStatusReadyToPlay: break; case AVPlayerStatusUnknown: break; case AVPlayerStatusFailed: break; } }else if ([keyPath isEqualToString:@"rate"]){ if (self.avPlayer.rate == 1) { } } }
隐藏/显示状态栏的方法:
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];这个方法在iOS9以后弃用了,而且须要
将View controller-based status bar appearance设置为NO;而下面的重写方法须要将View controller-based status bar appearance设置为YES,这个方法在iOS7以后就有了;
//刷新状态栏状态
[self setNeedsStatusBarAppearanceUpdate];app
#pragma mark -- 隐藏/显示状态栏的方法 /*[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];这个方法在iOS9以后弃用了,而且须要 将View controller-based status bar appearance设置为NO;而下面的重写方法须要将View controller-based status bar appearance设置为YES,这个方法在iOS7以后就有了; //刷新状态栏状态 [self setNeedsStatusBarAppearanceUpdate]; */ //设置样式 - (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } //设置是否隐藏 - (BOOL)prefersStatusBarHidden { return self.isHiddenStatusBar; } //设置隐藏动画 - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation { return UIStatusBarAnimationNone; }
//Block回调方法 typedef void(^FullScreenBlock)(BOOL isFull); typedef void(^ClosePLayerBlock)(); typedef void(^ShowBarBlock)(BOOL isShow); typedef void(^PlayFinishedBlock)(); @class GOVVideoPlayer; //代理方法 @protocol GOVVideoPlayerDelegate <NSObject> //播放结束 - (void)videoPlayerPlayFinished:(GOVVideoPlayer *)videoPlayer; //关闭播放器 - (void)videoPlayerClosePlayer:(GOVVideoPlayer *)videoPlayer; //全屏按钮 - (void)videoPlayerFullScreen:(GOVVideoPlayer *)videoPlayer withIsFull:(BOOL)isFull; //隐藏/展现footBar和topBar - (void)videoPlayerShowBar:(GOVVideoPlayer *)videoPlayer withIsShow:(BOOL)isShow;
GOVVideoPlayer是在继承于UIView的基础上封装的视频View;
GOVVideoController是在继承于UIViewController的基础上封装的视频视图控制器。
二者最大的不一样是在全屏和取消全屏的处理上面:前者是一个视图View,能够直接加在父视图上面,全屏时是加在 [UIApplication sharedApplication].keyWindow上的,然后者,小屏时是取GOVVideoController的View加在父视图上,全屏和取消全屏时是采用present和dismiss模态化转场的方法 。ide
iOS AVPlayer视频播放器动画
代码地址以下:
http://www.demodashi.com/demo/11168.htmlurl
注:本文著做权归做者,由demo大师代发,拒绝转载,转载须要做者受权spa