一:简介
AVFoundation是苹果在iOS和OS X系统中用于处理基于时间的媒体数据的Objective-C框架. 供使用者来开发媒体类型的应用程序。
上图是iOS系统下媒体应用的结构层. AVKit框架用于简化媒体应用的创建过程,如果你只需要看电影,那么使用这个就可以了, UKit可以支持简单的录制功能 . 而更多功能需要低层级框架支持.下面简单介绍下AVFoundation内最主要的支撑框架和其提供的功能。
-
CoreAudio : 处理所有音频事件.是由多个框架整合在一起的总称,为音频和MIDI内容的录制,播放和处理提供相应接口.设置可以针对音频信号进行完全控制,并通过Audio Units来构建一些复杂的音频处理.有兴趣的可以单独了解一下这个框架。
-
CoreMedia: 是AVFoundation所用到低层级媒体管道的一部分.提供音频样本和视频帧处理所需的低层级数据类型和接口。
-
CoreAnimation: 动画相关框架, 封装了支持OpenGL和OpenGL ES功能的ObjC各种类. AVFoundation可以利用CoreAnimation让开发者能够在视频的编辑和播放过程中添加动画和图片效果。
下面我就和大家详细的分享一下,如何使用AVFoundation来实现一个好用的视频播放器。如果好用或者对你有所帮助,不要忘了关注点个赞呦!!!
二:实现思路分析
-
视频控制界面实现
-
用于视频显示的View创建
-
视频数据下载器FBYVideoDownload创建
-
播放、暂停、横竖屏操作方法实现
-
监听播放进度
-
控制存储缓冲范围
-
拖动滑块,控制快进快退
-
定义临时文件路径
-
定义缓存文件夹路径
-
发起视频路径网路请求方法
-
播放结束设置
-
前后视频播放控制
三:实现源码分析
根据实现思路分析,一步步进行编码实现:
1. 视频控制界面实现
- (FBYVideoPlayerView *)videoPlayControl{ if (!_videoPlayControl) { _videoPlayControl = [[FBYVideoPlayerView alloc] initWithFrame:self.backgroundView.bounds]; [self.backgroundView addSubview:_videoPlayControl]; } return _videoPlayControl;}复制代码
2. 用于视频显示的View创建
- (UIView *)videoShowView{ if (!_videoShowView) { _videoShowView = [[UIView alloc] init]; _videoShowView.layer.masksToBounds = YES; [self.backgroundView addSubview:_videoShowView]; } return _videoShowView;}复制代码
3. 视频数据下载器FBYVideoDownload创建
@property(nonatomic, weak) iddelegate;//定义初始化方法 传入videoUrl参数(NSString)- (instancetype)initWithURL:(NSString *)videoUrl withDelegate:(id)delegate;//开始下载- (void)start;//暂停- (void)suspend;//关闭- (void)cancel;复制代码
4. 播放、暂停、横竖屏操作方法实现
//全屏 [_videoPlayControl setFullScreenButtonClick_block:^{ if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(videoPlayerDidFullScreenButtonClick)]) { [weakSelf.delegate videoPlayerDidFullScreenButtonClick]; } }]; //播放/暂停 [_videoPlayControl setPlayButtonClick_block:^(BOOL play) { if (play) { [weakSelf.player play]; }else{ [weakSelf.player pause]; } weakSelf.playButtonState = !weakSelf.playButtonState; }];复制代码
5. 监听播放进度
self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { CGFloat current = CMTimeGetSeconds(time); CGFloat total = CMTimeGetSeconds(weakSelf.currentPlayerItem.duration); CGFloat progress = current / total; weakSelf.videoPlayControl.currentTime = current; weakSelf.videoPlayControl.playValue = progress; if (weakSelf.isCanToGetLocalTime) { weakSelf.localTime = [weakSelf getLocalTime]; } NSInteger timeNow = [weakSelf getLocalTime]; if (timeNow - weakSelf.localTime > 1.5) { [weakSelf.videoPlayControl videoPlayerDidBeginPlay]; weakSelf.isCanToGetLocalTime = YES; } }];复制代码
6. 监听播放器的状态
[self.currentPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];复制代码
7. 监听当前的缓冲进度
[self.currentPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];复制代码
8. 监听到当前没有缓冲数据
[self.currentPlayerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];复制代码
9. 控制存储缓冲范围
- (void)playForActivity{ if (self.playButtonState) { [self.player play]; } self.isBufferEmpty = NO; self.isPlaying = YES; [self.videoPlayControl videoPlayerDidBeginPlay];}复制代码
10. 拖动滑块,控制快进快退
//拖动滑块[_videoPlayControl setSliderTouchEnd_block:^(CGFloat time) { [weakSelf seekToTimePlay:time]; }]; //快进快退[_videoPlayControl setFastFastForwardAndRewind_block:^(CGFloat time) { [weakSelf seekToTimePlay:time]; }];复制代码
11. 定义临时文件路径
self.videoTempPath = [NSString tempFilePathWithFileName:videoName];复制代码
12. 定义缓存文件夹路径
self.videoCachePath = [NSString cacheFilePathWithName:videoName];复制代码
13. 发起视频路径网路请求方法
- (void)sendHttpRequst{ [_fileHandle seekToEndOfFile]; NSURL *url = [NSURL URLWithString:_videoUrl]; NSMutableURLRequest *requeset = [NSMutableURLRequest requestWithURL:url]; //指定头信息 当前已下载的进度 [requeset setValue:[NSString stringWithFormat:@"bytes=%ld-", _curruentLength] forHTTPHeaderField:@"Range"]; //创建请求 NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:requeset]; self.dataTask = dataTask; //发起请求 [self.dataTask resume];}复制代码
14. 播放结束设置
- (void)playerItemDidPlayToEnd:(NSNotification *)notification{ //重新开始播放 __weak typeof(self) weak_self = self; [self.player seekToTime:CMTimeMake(0, 1) completionHandler:^(BOOL finished) { __strong typeof(weak_self) strong_self = weak_self; if (!strong_self) return; [strong_self.player play]; }];}复制代码
15. 前后视频播放控制
//进入后台- (void)appDidEnterBackground{ if (self.stopWhenAppDidEnterBackground) { [self pauseVideo]; }}//进入前台- (void)appDidEnterForeground{ [self playVideo];}复制代码
五:项目实际使用
1. 下载demo
下载demo,将demo中FBYVideoData文件夹引入项目中。
2. 在项目中引入FBYVideoPlayer并继承FBYVideoPlayerDelegate代理
#import "FBYVideoPlayer.h"@interface ViewController ()@property (nonatomic ,strong) FBYVideoPlayer *videoPlayer;@property (nonatomic ,strong) UIView *videoPlayBGView;@property (nonatomic ,copy) NSString*videoUrl;@end复制代码
3. 初始化创建基层view
self.videoPlayBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 90, SCREEN_WIDTH, SCREEN_WIDTH * 0.6)];self.videoPlayBGView.backgroundColor = [UIColor blackColor]; [self.view addSubview:self.videoPlayBGView];复制代码
4. 初始化调用视频播放方法
self.videoPlayer = [[FBYVideoPlayer alloc] init];self.videoPlayer.delegate = self;[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];复制代码
5. 初始化调用视频播放方法
self.videoPlayer = [[FBYVideoPlayer alloc] init];self.videoPlayer.delegate = self;[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];复制代码
本篇文章demo源码:
希望可以帮助大家,如有问题可加QQ技术交流群: 668562416 如果哪里有什么不对或者不足的地方,还望读者多多提意见或建议
如需转载请联系我,经过授权方可转载,谢谢
本篇已同步到个人博客:
欢迎关注我的公众号:网罗开发