代码地址如下:
http://www.demodashi.com/demo/11168.html

一、运行效果

二、实现过程

①、创建播放器avPlayer

       //创建播放器
url = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:url]];
self.avPlayer = player;

②、创建显示屏_videoLayer

- (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];

#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;
}

④、创建用于处理播放结束、关闭播放器、全屏/退出全屏、隐藏/展示footBar和topBar的Block回调方法和代理方法,方便用户做些自定义的操作。

//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模态化转场的方法 。

iOS AVPlayer视频播放器

代码地址如下:
http://www.demodashi.com/demo/11168.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

iOS AVPlayer视频播放器的更多相关文章

  1. 项目源码--IOS自定义视频播放器

    下载源码 技术要点: 1. 视频播放器功能的实现 2. 视频文件的扫描与管理 3. Ipad UI的实现 4.源码详细的中文注释 ……. 详细介绍: 1. 视频播放器功能的实现 源码基于MediaPl ...

  2. ios系统视频播放器MPMoviePlayerController应用遇到的坑

    最近在做视频播放时应用系统MPMoviePlayerController播放器播放视频,发现点击快进快退会出现黑屏现象,并且点击完成按钮也不会返回,代码以及界面如下所示: NSURL *url=[se ...

  3. ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)

    ABBPlayerKit ios开发视频播放后台下载功能实现 : 代码下载地址:https://github.com/niexiaobo/ABBPlayerKit github资料学习和下载地址:ht ...

  4. iOS:基于AVPlayer实现的视频播放器

    最近在学习AVFoundation框架的相关知识,写了一个基于AVPlayer的视频播放器,相关功能如下图: 代码github:https://github.com/wzpziyi1/VideoPla ...

  5. iOS - AVPlayer 音视频播放

    前言 NS_CLASS_AVAILABLE(10_7, 4_0) @interface AVPlayer : NSObject @available(iOS 4.0, *) public class ...

  6. iOS 调用音乐播放以及视频播放器

    音乐播放 NSString *path = [[NSBundle mainBundle] pathForResource:@"预谋" ofType:@"mp3" ...

  7. iOS 音视频播放

    播放控制切换为: ijkplayer wiki: https://github.com/changsanjiang/SJVideoPlayer/wiki/Use-ijkplayer 播放控制切换为: ...

  8. C语言基于GTK+Libvlc实现的简易视频播放器

    小编心语:现下,各种视频播放软件层出不穷,竞争也越演越烈,不知道大家有木有这个想法,小编有时在想能不能做一款属于自己的视频播放器呢~小编特意去实验楼,整理出了这篇关于如何实现简易视频播放器的博文.简易 ...

  9. iOS音乐播放器相关

    iOS音乐播放器框架主要有两大类:AvPlayer.AvaudioPlayer AvPlayer 能播放本地及网络歌曲 AvaudioPlayer 能播放本地歌曲.有相关代理方法(其实也可以播放网络歌 ...

随机推荐

  1. VB 中DTpicker日期控件的运用

    1.如何加载 VB默认的控件栏中是没有DTpicker日期控件的,添加过程:工具--部件--控件--"Microsoft  Windows Common Controls-2.6.0&quo ...

  2. 初见Python<4>:字典

    序列是python中的一种数据结构,映射是另一种.映射(mapping)通过名字来引用值.python内建的唯一一种映射结构是字典.字典中的值没有特殊的顺序,但都存储在一个特定的键中.键可以是数字.字 ...

  3. BZOJ 4031 [HEOI2015]小Z的房间(Matrix-Tree定理)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4031 [题目大意] 你突然有了一个大房子,房子里面有一些房间. 事实上,你的房子可以看 ...

  4. 【推导】【分类讨论】Codeforces Round #431 (Div. 1) B. Rooter's Song

    给你一个这样的图,那些点是舞者,他们每个人会在原地待ti时间之后,以每秒1m的速度向前移动,到边界以后停止.只不过有时候会碰撞,碰撞之后的转向是这样哒: 让你输出每个人的停止位置坐标. ①将x轴上初始 ...

  5. http请求 url 传递参数(特殊字符)解决方法

    有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码       十六进制值 1. + URL 中+号表示空格 %2B ...

  6. Problem F: 尖兵

    #include<stdio.h> struct man{ ]; int grade; }; int main(void) { int t; int i,j,n; ],max; scanf ...

  7. Integer引用类型问题

    public class TestMain { public static void main(String[] args) { Integer integer = 2; go(2); System. ...

  8. WPF中的动画——(五)关键帧动画

    与 From/To/By 动画类似,关键帧动画以也可以以动画形式显示目标属性值. 和From/To/By 动画不同的是, From/To/By 动画只能控制在两个状态之间变化,而关键帧动画则可以在多个 ...

  9. [Bug]Object reference not set to an instance of an object.

    引言 今天在客户这儿,由一个问题导致,需求的变化,不得不修改代码,在记录日志中出现该问题. 原因 通过id查找相关信息,没有判断是否为null,集合是否有数据. Object reference no ...

  10. 解决myeclipse不编译的方法

    请按照下面方法对号入座: MyEclipse不编译解决1. 确保 project->build automatically 已经被选上(最基本). MyEclipse不编译解决2. 如果选上了, ...