『ios』AVPlayer 从入门到待续。

db222a46264172e2ca07c2378daa84e8.jpg

因为一直没有一个专门做视频的项目来具体真正实践AVPlayer这块知识,算是拾补遗漏的知识吧,我想也可以给还没入门的你做一个好的开始。

AVPlayer的组成?

AVPlayer:控制播放器的播放,暂停,播放速度
AVURLAsset : AVAsset 的一个子类,使用 URL 进行实例化,实例化对象包换 URL 对应视频资源的所有信息。
AVPlayerItem:管理资源对象,提供播放数据源
AVPlayerLayer:负责显示视频,如果没有添加该类,只有声音没有画面
然后再加上一些通知,就足够做一个可以用的简单播放器了。

如何搞一个能看得的见摸得着的播放器?

通过构造可以看出需要 AVPlayerLayer AVPlayer AVPlayerItem 这三个相互结合才能看到。

    self.avPlayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    UIView *bgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 300)];
    bgView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:bgView];
    
    [bgView.layer addSublayer:self.avPlayer];
    self.avPlayer.frame = bgView.bounds;
    
    AVPlayerItem *item = [[AVPlayerItem alloc]initWithURL:[NSURL    URLWithString:@"http://flv3.bn.netease.com/videolib3/1604/14/LSwHa2712/SD/LSwHa2712-mobile.mp4"]];
    self.currentItem = item;
    [self.player replaceCurrentItemWithPlayerItem:self.currentItem];

-(AVPlayer *)player{
    if (!_player) {
        _player = [[AVPlayer alloc]init];
    }
    return _player;
}

视频播放器能看得见了,但是怎么控制呢?

status

可以根据这个状态来控制播放器的播放。

    [self.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ 
if ([object isKindOfClass:[AVPlayerItem class]]) { 
if ([keyPath isEqualToString:@"status"]) { 
switch (_playerItem.status) { 
case AVPlayerItemStatusReadyToPlay:   
//推荐将视频播放放在这里 
[self play]; 
break; 
case AVPlayerItemStatusUnknown: 
NSLog(@"AVPlayerItemStatusUnknown"); 
break; 
case AVPlayerItemStatusFailed: 
NSLog(@"AVPlayerItemStatusFailed") 
break; 
default: 
break; 
} 
} 
}

CMTime

这个是视频相关的信息,如视频的总时间,视频的当前播放时间 都与这个有关。

typedef struct{ 
CMTimeValue value; // 帧数 
CMTimeScale timescale; // 帧率(影片每秒有几帧) 
CMTimeFlags flags; 
CMTimeEpoch epoch; 
} CMTime; 

我们在项目中,总是会有一种需求那就是获取当前的播放时间,这个其实很好办,系统有个回调函数

- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block; 

方法名如其意, “添加周期时间观察者” ,参数1 interal 为CMTime 类型的,参数2 queue为串行队列,如果传入NULL就是默认主线程,参数3 为CMTime 的block类型。
简而言之就是,每隔一段时间后执行 block。
比如:我们把interval设置成CMTimeMake(1, 10),在block里面刷新label,就是一秒钟刷新10次。
[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) { 

AVPlayerItem *item = WeakSelf.playerItem; 
NSInteger currentTime = item.currentTime.value/item.currentTime.timescale; 
NSLog(@"当前播放时间:%ld",currentTime); 
}]; 

缓存相关

loadedTimeRange 缓存时间
获取视频的缓存情况我们需要监听playerItem的loadedTimeRanges属性 KVO,这样我们可以通过获取的数值来实现相关的ui。

[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; 

if ([keyPath isEqualToString:@"loadedTimeRanges"]){ 
NSArray *array = _playerItem.loadedTimeRanges; 
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围 
float startSeconds = CMTimeGetSeconds(timeRange.start); 
float durationSeconds = CMTimeGetSeconds(timeRange.duration); 
NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度 
NSLog(@"当前缓冲时间:%f",totalBuffer); 
} 

playbackBufferEmpty

监听playbackBufferEmpty我们可以获取当缓存不够,视频加载不出来的情况:

[self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 

在KVO回调里:

if ([keyPath isEqualToString:@"playbackBufferEmpty"]) { 

//some code show loading 
} 

playbackLikelyToKeepUp

playbackLikelyToKeepUp和playbackBufferEmpty是一对,用于监听缓存足够播放的状态

[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 
/* ... */ 
if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { 
//由于 AVPlayer 缓存不足就会自动暂停,所以缓存充足了需要手动播放,才能继续播放 
[_player play]; 
} 

项目中可能会遇到的问题。

项目中肯定会遇到滑动滑块的需求吧!滑动滑块来改变时间改变播放

    [self.slideView addTarget:self action:@selector(SliderEndChangeValue:) forControlEvents:UIControlEventValueChanged];
    [self.slideView addTarget:self action:@selector(startSlider) forControlEvents:UIControlEventTouchDown];
    [self.slideView addTarget:self action:@selector(endSlider) forControlEvents:UIControlEventTouchUpInside];
-(void)SliderEndChangeValue:(id)sender{//滑动
    NSLog(@"%lf",self.slideView.value);
    [self removeProgressTimer];
    [self removeShowTimer];
    if (self.slideView.value == 1) {
        self.slideView.value = 0;
    }
    NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentItem.duration) * self.slideView.value;
    NSTimeInterval duration = CMTimeGetSeconds(self.player.currentItem.duration);
    self.showLabel.text = [self stringWithCurrentTime:currentTime duration:duration];
    [self addShowTimer];
//    [self addProgressTimer];
}
-(void)startSlider{//开始滑动
    [self removeProgressTimer];
}
-(void)endSlider{//停止滑动
    [self addProgressTimer];
    NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentItem.duration) * self.slideView.value;
    [self.player seekToTime:CMTimeMakeWithSeconds(currentTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}

暂时说这么多,后面还会继续补充。下面是demo地址,文章会持续更新...欢迎关注
https://github.com/Butteryflyyer/XHAVPlayer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343