OC AVPlayerItem,AVPlayer,AVPlayerLayer的使用

音量调节以及跳转到指定的秒数,停止和暂停,只是学习,没有封装

1#import <Masonry.h> 2#import <AVFoundation/AVFoundation.h> 3@interface RecordVideoplayVC () 4@property(nonatomic,strong)AVPlayerItem *avPlayerItem; 5@property(nonatomic,strong)AVPlayer *avPlayer; 6@property (nonatomic ,strong) id playbackTimeObserver; 7@end 8 9@implementation RecordVideoplayVC 10 11- (void)viewDidLoad { 12 [super viewDidLoad]; 13 // Do any additional setup after loading the view. 14// AVPlayerItem:提供视频信息,一个AVPlayerItem对应着你提供的一个视频Url资源,这个理解它的时候可以把它比作一个Model, 你初始化了AVPlayerItem之后,并不是马上就可以使用它了,因为凡是和Url网络扯上关系的,都需要时间,等AVPlayerItem加载好之后就可以使用它了,那这一步我们怎么处理呢? 15// 答案是利用KVO观察statues属性为 AVPlayerStatusReadyToPlay,看看这个属性的定义: 16 17// @property (nonatomic, readonly) AVPlayerStatus status 它是一个只读属性,这点也需要注意,其实也就理解利用KVO的原因。 18// 19// 2>: 顺便总结要是你要显示当前视屏的缓存进度,你需要监测它的loadedTimeRanges属性。 20// 21// 2、AVPlayerLayer 22// 23// 它主要负责的就是视频的显示,继承自CALayer,其实你可以把它理解成我们的View。我们自定义的那些播放时候的控件就是添加在它上面的,比如我们能看到的播放按钮,停止按钮,或者播放进度条等等。 24 25// 3、 AVPlayer 26// 27// 它主要负责的是管理视频播放,暂停等等,相当于一个视频管理器,要是类比的话他就是一个ViewController(当然不是真正的ViewController),这三者就基本含括了一个基本的视频播,基于着三者我们总结一下播放一个视频的基本的过程: 28 29// 首先,得到视频的URL 30// 根据URL创建AVPlayerItem 31// 把AVPlayerItem 提供给 AVPlayer 32// AVPlayerLayer 显示视频。 33// AVPlayer 控制视频, 播放, 暂停, 跳转 等等。 34// 播放过程中获取缓冲进度,获取播放进度。 35// 视频播放完成后做些什么,是暂停还是循环播放,还是获取最后一帧图像。 36 37// 4、AVPlayerViewController 38// 39// 它是Apple 帮我们封装好的可以一个视频播放控制器,它就有一个 @property (nonatomic, strong, nullable) AVPlayer *player 的属性,前面的AVPlayer也就像相应的需要赋值给它,它里面还有一些我们需要理解一下的属性,我们也把它写出来,具体代码我们下面再看: 40// 41// player: 设置播放器 42// showsPlaybackControls: 设置是否显示媒体播放组件,默认YES 43// videoGravity: 设置视频拉伸模式 44// allowsPictureInPicturePlayback: 设置是否允许画中画回放,默认YES 45// delegate: 设置代理 46// 5、AVPlayerViewControllerDelegate 47// 48// 这个代理就是前面说的AVPlayerViewController的协议,它主要的是为画中画的设置的代理,前面介绍 AVPlayerViewController 的时候有看到过一个是否允许画中画的属性,具体什么是画中画相信大家都了解,看过直接的朋友应该都看到了这个技术点的具体应用。我们看看它里面的饭法规主要都干了些什么? 49// // 1、即将开始画中画 50// - (void)playerViewControllerWillStartPictureInPicture:(AVPlayerViewController *)playerViewController; 51// // 2、开始画中画 52// - (void)playerViewControllerDidStartPictureInPicture:(AVPlayerViewController *)playerViewController; 53// // 3、画中画失败 54// - (void)playerViewController:(AVPlayerViewController *)playerViewController failedToStartPictureInPictureWithError:(NSError *)error; 55// // 4、即将结束画中画 56// - (void)playerViewControllerWillStopPictureInPicture:(AVPlayerViewController *)playerViewController; 57// // 5、结束画中画 58// - (void)playerViewControllerDidStopPictureInPicture:(AVPlayerViewController *)playerViewController; 59 60 61 62 // Do any additional setup after loading the view. 63 64 65 self.avPlayerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:MovieURL]]; 66 self.avPlayer = [[AVPlayer alloc]initWithPlayerItem:self.avPlayerItem]; 67 AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; 68 avPlayerLayer.frame = CGRectMake(10, 100, 355, 200); 69 [self.view.layer addSublayer:avPlayerLayer]; 70 71 //状态添加观察者 72 [self.avPlayerItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil]; 73 // 缓存进度添加观察者 74 [self.avPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; 75 // 添加视频播放结束通知 76 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayerItem]; 77 78 79 80 self.avPlayer.volume = 0.5;//调节音量 0-1 81 82} 83 84- (void)moviePlayDidEnd:(NSNotification *)notification { 85 NSLog(@"Play end"); 86 87 __weak typeof(self) weakSelf = self; 88 [self.avPlayer seekToTime:kCMTimeZero completionHandler:^(BOOL finished) { 89 //把进度跳转到0, 90 }]; 91} 92 93-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ 94 95 AVPlayerItem * avplayeritem = (AVPlayerItem *)object; 96 if ([keyPath isEqualToString:@"status"]) { 97 98 AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; 99 if (status == AVPlayerStatusReadyToPlay) { 100 NSLog(@"准备好播放"); 101 CMTime duration = avplayeritem.duration; 102 NSLog(@"视频总时长:%.2f",CMTimeGetSeconds(duration));//总时长 103 // 播放 104 [self.avPlayer play]; 105 [self monitoringPlayback];// 监听播放状态 106 107 }else if (status == AVPlayerStatusFailed){ 108 NSLog(@"视频准备发生错误"); 109 }else{ 110 NSLog(@"位置错误"); 111 } 112 }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){ 113 114 // 可以自定义缓存进度 115 NSTimeInterval timeInterval = [self alreadyCacheVideoProgress]; 116 NSLog(@"视频已经缓存的时长:%.2f",timeInterval); 117 } 118} 119 120#pragma mark -- 121#pragma mark -- alreadyCacheVideoProgress 122-(NSTimeInterval)alreadyCacheVideoProgress{ 123 // 先获取到它的缓存的进度 124 NSArray * cacheVideoTime = [self.avPlayerItem loadedTimeRanges]; 125 // CMTimeRange 结构体 start duration 表示起始位置 和 持续时间 126 // 获取缓冲区域 127 CMTimeRange timeRange = [cacheVideoTime.firstObject CMTimeRangeValue];//NSValue 128 float startSeconds = CMTimeGetSeconds(timeRange.start); 129 float durationSeconds = CMTimeGetSeconds(timeRange.duration); 130 131 // 计算总缓冲时间 = start + duration 132 NSTimeInterval result = startSeconds + durationSeconds; 133 return result; 134} 135 136 137 138-(void)dealloc{ 139 [self.avPlayerItem removeObserver:self forKeyPath:@"status"]; 140 [self.avPlayerItem removeObserver:self forKeyPath:@"loadedTimeRanges"]; 141 [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayerItem]; 142 [self.avPlayer removeTimeObserver:self.playbackTimeObserver]; 143} 144 145//监听播放状态 146- (void)monitoringPlayback { 147 /* 148 CMTime CMTimeMake( 149 int64_t value, //秒 150 int32_t timescale)//次数 151 */ 152 self.playbackTimeObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5) queue:NULL usingBlock:^(CMTime time) { 153 CGFloat currentSecond = self.avPlayerItem.currentTime.value/self.avPlayerItem.currentTime.timescale;// 计算当前在第几秒 154 //如果需要进度条的话,这里可以更新进度条 155 }]; 156} 157//跳转到指定的秒数 158-(void)jumptoValue:(float)seconds{ 159 CMTime changedTime = CMTimeMakeWithSeconds(seconds, 1); 160 [self.avPlayer seekToTime:changedTime completionHandler:^(BOOL finished) { 161 [self.avPlayer play]; 162 }]; 163 164} 165 166 167// 168 169@end
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

一篇文章带你了解JavaScript日期

日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用