最近在琢磨视频播放,现在重新梳理下发出来。

现在实现的功能为:播放本地、网络视频,进度条,缓冲条,加载圈,暂停,开始,拖拽控制进度,滑动控制亮度及声音这些基本功能。

利用控件AVPlayer。

一、搭建基本控件

利用AVPlayer实现的视频播放需要三个控件,AVPlayer,AVPlayerItem,AVPlayerLayer,

其中player用于宏观调控,控制视频的播放暂停等,

item用于存储视频数据属性,比如视频播放的时长等

layer用于展示播放器图层,

可以类比MVC,player对应Controlelr,layer对应View,item对应Model,这样就很好理解了,

基本原理懂了以后就是开始搭建播放器了。

    mItem = [AVPlayerItem playerItemWithURL:url];mPlayer =[AVPlayer playerWithPlayerItem:mItem];mLayer = [AVPlayerLayer playerLayerWithPlayer:mPlayer];mLayer.frame = self.bounds;mLayer.videoGravity = AVLayerVideoGravityResize;[self.layer addSublayer:mLayer];

通过以上代码就能实现简单的视频播放,

这里需要注意的是videoGravity属性,用于管理你的视频填充方式,根据视频类型调整。

二、通过观察者对视频进行监控

这里先将常用的观察者给大家说明一下:

其中:

1、status:用于判断视频状态,不过需要注意的是这里有两种状态,一种是播放数据的准备状态AVPlayerItemStatus,一种是播放器的准备状态AVPlayerStatus.一般都是根据AVPlayerItemStatus来判断视频是否可用,大家也可按需选择。

这里以AVPlayerItemStatus为例,status里面有三个状态

AVPlayerItemStatusReadyToPlay - 视频数据已准备好,随时可以播放,一般在这里开始视频的播放。

AVPlayerItemStatusUnknown - 视频资源未找到,

AVPlayerItemStatusFailed - 视频资源加载失败。

2、loadedTimeRanges:缓冲进度,可以通过此观察者设置缓冲条。

3、playbackBufferEmpty:在跳转播放时,数据不能加载成功,播放失败。一般在此处进行失败提示。

4、playbackLikelyToKeepUp:在跳转播放时,数据已缓冲好,随时可以播放,一般在此处将缓冲的加载圈停止。

5、addPeriodicTimeObserverForInterval,这个是AVPlayer自带的方法,可以查看播放的进度,可以用此方法控制进度条的前进后退等。

需要注意的是记得移除观察者,否则可能造成不可预知的bug。

以下是这部分的代码:

#pragma mark - 添加通知
- (void)addObserver
{// 视频播放状态[mItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];// 缓冲进度[mItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];[mItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];[mItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieToEnd) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];}
// 添加时间观察者
- (void)addTimeObserver
{// 当前播放时间__weak UISlider * weakSlider = mSlider;mTimeObserver = [mPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) {double currentLength = time.value/(time.timescale*1.0);weakSlider.value = currentLength/mTimeLength;NSLog(@"%d",(int)time.value/time.timescale);}];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {dispatch_async(dispatch_get_main_queue(), ^{// 确保回到主线程AVPlayerItem *item = (AVPlayerItem *)object;if ([keyPath isEqualToString:@"status"]) {AVPlayerItemStatus status = item.status;switch (status) {case AVPlayerItemStatusReadyToPlay:{NSLog(@"AVPlayerItemStatusReadyToPlay");mTimeLength =  item.duration.value/(item.duration.timescale * 1.0);[mPlayer play];[mActivityView stopAnimating];[self addTimeObserver];}break;case AVPlayerItemStatusUnknown:{NSLog(@"AVPlayerItemStatusUnknown");}break;case AVPlayerItemStatusFailed:{NSLog(@"AVPlayerItemStatusFailed");NSLog(@"%@",mItem.error);}break;default:break;}} else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {NSLog(@"loadedTimeRanges");// 设置缓冲条[self setProgressValue];} else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {NSLog(@"playbackBufferEmpty");// seekToTime后,缓冲数据为空,而且有效时间内数据无法补充,播放失败}else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {NSLog(@"playbackLikelyToKeepUp");// seekToTime后,可以正常播放,相当于readyToPlay[mActivityView stopAnimating];}});}

三、进度条(CMTime介绍)

进度条用的UISlider,进度条的进度是根据时间观察者调控的,具体可以看上面介绍的时间观察者代码。

这里需要注意的是,在拖动进度条的时候,需要用到方面seekToTime,用于跳到对应的时间,

而seekToTime需要传的参数是CMTime,CMTime通过CMTimeMake(2,1)来创建,前面的数字/后面的数字即为当前时间,也就是说CMTime是根据分数算时间的,还有好多其他用法,大家可自行研究学习。

以下为此部分核心代码:

 [mSlider addTarget:self action:@selector(sliderChange) forControlEvents:UIControlEventValueChanged];
// 滑动slider
- (void)sliderChange
{[mActivityView startAnimating];[mPlayer seekToTime:CMTimeMake(mSlider.value * mTimeLength, 1)];
}

四、缓冲条

缓冲条用UIProgressView实现,

这里需要注意的是缓冲条和进度条的配合,slider两端设为透明,这样就能显示出下面的进度条了。

就是这个效果。

缓冲条的逻辑在观察者loadedTimeRanges里实现,具体代码如下:

- (void)setProgressValue
{// 获取缓冲区域CMTimeRange timeRange = [[mItem.loadedTimeRanges firstObject] CMTimeRangeValue];double start = CMTimeGetSeconds(timeRange.start);double duration = CMTimeGetSeconds(timeRange.duration);// 设置缓冲条if (mTimeLength == 0) {mProgress.progress = 0;}else{[mActivityView stopAnimating];mProgress.progress = (start + duration)/mTimeLength;}}

五、通过滑动实现快进,亮度,声音的调节

这里用到的是拖动手势UIPanGestureRecognizer,并通过其滑动的方向来定义各个功能

逻辑不多,直接贴代码:

// 滑动屏幕
- (void)panChange:(UIPanGestureRecognizer *)pan
{if (pan.state == UIGestureRecognizerStateBegan) {// 开始mBegainPoint = [pan locationInView:self];[mActivityView startAnimating];}else if (pan.state == UIGestureRecognizerStateChanged) {// 改变}else if (pan.state == UIGestureRecognizerStateEnded) {// 结束mEndPoint = [pan locationInView:self];[self controlSlidePurpose];}
}
// 控制滑动的目的:
-(void)controlSlidePurpose
{if (fabs(mEndPoint.x - mBegainPoint.x) > fabs(mEndPoint.y - mBegainPoint.y)) {// 快进or快退double current = mPlayer.currentTime.value/mPlayer.currentTime.timescale;[mPlayer seekToTime:CMTimeMake(current+(mEndPoint.x - mBegainPoint.x), 1)];}else if (mBegainPoint.x < self.bounds.size.width/2){// 亮度调整(通过添加图层并调整alpha即可,这里并没写)}else if (mBegainPoint.x > self.bounds.size.width/2){// 声音调整if (mEndPoint.y - mBegainPoint.y >0) {mPlayer.volume -= 0.2;}elsemPlayer.volume += 0.2;/*mPlayer.volume这个可以控制音量 但官方推荐使用 MPVolumeView*/}
}

六、总结

都是基本功能,所以代码并不多,两三百行代码足够了,需要注意的是各种情况的判断以及加载圈出现消除的时机,做好实现一个简单的播放器并不困难。

接下来就是功能优化了,下载,缓存,等等,有时间在慢慢优化吧。

七、遇到的问题

1、视频播放失败,提示AVPlayerItemStatusFailed

在从test工程移到自己的工程时,发现视频播放失败,AVPlayerItemStatusFailed总是提示失败,查了好久才解决

在plist文件里添加属性

<key>NSAppTransportSecurity</key>
<dict><key>NSAllowsArbitraryLoads</key><true/>
</dict>

就可以正常播放了

通过AVPlayer实现视频播放相关推荐

  1. AVPlayer进行视频播放

    一.说明 AVPlayer是AVFoundation框架中的一个类,它比较接近于底层,可以利用该类进行自定义样式的视频播放.AVPlayer本身并不能显示视频,如果AVPlayer要显示视频,则它必须 ...

  2. AVPlayer实现视频播放

    Demo 实现功能: 1.视频的播放/暂停 2.播放进度前进后退 ViewController import AVFoundation/AVFoundation.h import "TQPl ...

  3. AVPlayer自定义视频播放器

    我的avplayer播放器,能横屏,竖屏,适应屏幕,上代码 1.我把我的那个最主要的类的.m的主要的代码附上 @implementation LDZMoviePlayerController- (vo ...

  4. iOS 教你使用MP、AVPlayer、AVPlayerVC构建一个完整的视频播放器

    1.前言 标题必须要浮夸!要感觉像是一个大新闻.长者如是说. 其实是前几天去面试的时候,被要求说必须做过视频播放相关项目.有点闹心之余,就花了点时间在家写了一个简单播放器,基本实现了主流播放器的大致功 ...

  5. AVPlayer自定制视频播放器(2)——耳机线控、中断以及AVAudioSession的使用

    在上一篇博客中说到了使用AVPlayer进行自定义视频播放器.这里讲继续讲述视频播放器的自定制.下面是上一篇博客的链接,本篇博客将承接上一篇博客进行讲解,如果有AVPlayer自定制视频播放器基础的同 ...

  6. 【iOS开发进阶】-AVPlayer视频播放

    1.AVPlayer介绍 iOS提供了多种方法来实现视频播放,包括MPMoviePlayerController,MPMoviePlayerViewController,AVPlayer,AVPlay ...

  7. nPlayer Plus视频播放器 免越狱直装

    这是一款付费软件,略有小贵,plus版本为60元,普通版本为30元,lite版本为免费,但是会有广告.前几年买过一款叫Avplayer的视频播放器,听这个名字就很有诱惑力,但是刚买不久,它就不更新了. ...

  8. iOS 视频播放从零开始(二)

    iOS 9之后苹果推荐使用AVPlayer进行视频播放,AVPlayer相对于MPMediaPlayerViewController功能更加强大,有更多的灵活性,当然,也需要你去自定义构建UI.其他优 ...

  9. swiftui视频_swiftui视频播放器实时处理核心图像

    swiftui视频 SwiftUI in iOS 14 introduced native support for playing movie files. The new VideoPlayer c ...

最新文章

  1. Linux shell 学习笔记(5)— 文件权限(添加、修改、删除用户及创建、修改群组)
  2. 修改以服务方式启动tomcat7的堆内存设置
  3. ModelSim之命令行仿真入门 (step 2)
  4. php接收流文件,PHP传输文件流及文件流的保存
  5. MSN即将退役,即时通讯开放平台成趋势
  6. 前端radio单选框默认选中_开发记录篇前端内容1
  7. 03MyBatis的事务管理和缓存机制
  8. MongoDB可视化工具RoboMongo----Windows安装
  9. Python字符串中常用的方法
  10. macbook 安装任意来源
  11. mysql 序列号_mysql 序列号生成器(转)
  12. matlab 脉冲压缩算法,雷达脉冲压缩matlab
  13. quartus如何生成sof_JIC文件生成和固化详细步骤
  14. Win 10 忘记密码不用U盘就可解决
  15. DDOS渗透与攻防(二)之SYN-Flood攻击
  16. Chrome浏览器运行超图三维场景
  17. Codeforces 877 E Danil and a Part-time Job(线段树+dfs序)
  18. CentOS6.5X86_64系统定制文档详细版
  19. 开源ERP Tryton 的用户权限管理
  20. php 开头结尾,php 字符串 以什么开头 开头开始 以什么结尾 结束 包含 startWith endWith 字符串包含 有大用...

热门文章

  1. 算法竞赛——进阶指南——acwing214. Devu和鲜花 容斥原理
  2. 常见功能测试点的测试用例大全(干货)
  3. sqlserver2005 express 及SSMS安装小记
  4. oracle去掉prompt,oracle提示符sqlprompt
  5. USB移动存储外设在设计行业的管控建议
  6. 能够观看全球实时网路攻击的地图
  7. nginx启动失败(bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket…permissions)
  8. python绿色参数_色差估计在python
  9. linux使用keytool生成证书库,使用JDK自带的keytool工具生成证书
  10. C语言素数因子思路,完美解决质因子(素数+因数)(C语言代码)