AVPlayer
在iOS開發(fā)中,播放視頻通常有兩種方式,一種是使用MPMoviePlayerController(需要導(dǎo)入MediaPlayer.Framework),還有一種是使用AVPlayer。AVPlay既可以用來播放音頻也可以用來播放視頻,AVPlay在播放音頻方面可以直接用來播放網(wǎng)絡(luò)上的音頻。在使用AVPlay的時(shí)候我們需要導(dǎo)入AVFoundation.framework框架,再引入頭文件#import<AVFound
ation/AVFoundation.h>。
AVPlayer視頻播放
在開發(fā)中,單純的使用AVPlayer類是無法現(xiàn)實(shí)視頻的,要將視頻添加到AVPlayerLayer中,這樣才能將視頻現(xiàn)實(shí)出來,所以我們先在@interface中添加一下屬性
@property (strong, nonatomic)AVPlayer *myPlayer;//播放器
@property (strong, nonatomic)AVPlayerItem *item;//播放單元
@property (strong, nonatomic)AVPlayerLayer *playerLayer;//播放界面(layer)
我們簡(jiǎn)單介紹一下這三個(gè)屬性之間的關(guān)系吧
首先我們之所以能夠看到視頻是因?yàn)锳VPlayerLayer幫我們把視頻呈現(xiàn)出來了,可以說是AVPlayerLayer就是一個(gè)視頻播放器的載體,它負(fù)責(zé)需要播放的畫面。用MVC比喻,就是AVPlayerLayer屬于V層,負(fù)責(zé)對(duì)用戶的呈現(xiàn)。從AVPlayerLayer的便利構(gòu)造器方法中可以看出我們?cè)趧?chuàng)建一個(gè)AVPlayerLayer的時(shí)候需要一個(gè)AVPlayer類型的參數(shù)。所以在創(chuàng)建AVPlayerLayer的時(shí)候,我們需要先有一個(gè)AVPlayer,它用MVC來分類的話就相當(dāng)于MVC中的C層,負(fù)責(zé)播放單元和播放界面的協(xié)調(diào)工作,我們?cè)谒谋憷麡?gòu)造器方法中可以看到他需要我們傳入一個(gè)AVPlayerItem也就是播放單元,所謂的播放單元就是給播放器提供了一個(gè)數(shù)據(jù)的來源,用MVC來類比的話,它就屬于M層,在創(chuàng)建一個(gè)播放單元的時(shí)候,我們首先得需要一個(gè)網(wǎng)址。
綜上所述,將一個(gè)視頻播放出來可分為如下幾個(gè)步驟。
第一步:首先我們需要一個(gè)播放的網(wǎng)址
NSURL *mediaURL = [NSURL URLWithString:@"http://baobab.wdjcdn.com”]
第二步:初始化一個(gè)播放單元
self.item = [AVPlayerItem playerItemWithURL:mediaURL];
第三步:初始化一個(gè)播放器對(duì)象
self.myPlayer = [AVPlayer playerWithPlayerItem:self.item];
第四步:初始化一個(gè)播放器的Layer
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.myPlayer];
self.playerLayer.frame = CGRectMake(0, 0, self.view.bounds.size.width, 500);
[self.view.layer addSublayer:self.playerLayer];
第五步:開始播放
[self.myPlayer play];
只要順序執(zhí)行上面的五個(gè)步驟,就可以將一個(gè)視頻播放到界面上。當(dāng)然現(xiàn)在還只是能夠播放了而已,要具體實(shí)現(xiàn)視頻的快進(jìn)快退功能,請(qǐng)繼續(xù)往下看。
AVPlayer視頻快進(jìn)快退
播放進(jìn)度 CMTime類型一般是用來表示視頻或者動(dòng)畫的時(shí)間類型。CMTime對(duì)象的Value屬性是用來得到當(dāng)前視頻或者動(dòng)畫一共有多少幀,timescale指的是每秒多少幀;timescale指的是每秒多少幀,value/timescale = 視頻的總時(shí)長(zhǎng)(秒)
視頻的快進(jìn)快退,首先我們聲明了兩個(gè)屬性
@property (strong, nonatomic)UISlider *avSlider;//用來現(xiàn)實(shí)視頻的播放進(jìn)度,并且通過它來控制視頻的快進(jìn)快退。
@property (assign, nonatomic)BOOL isReadToPlay;//用來判斷當(dāng)前視頻是否準(zhǔn)備好播放。
在這里我們將上面前四個(gè)步驟封裝到一個(gè)方法中,并且在這個(gè)方法中給播放單元也就是AVPlayerItem添加一個(gè)監(jiān)聽,來監(jiān)聽它的狀態(tài)。
-(void)avPlayerMethod{
//構(gòu)建播放網(wǎng)址
NSURL *mediaURL = [NSURL URLWithString:@"http://baobab.wdjcdn.com/1455782903700jy.mp4"];
//構(gòu)建播放單元
self.item = [AVPlayerItem playerItemWithURL:mediaURL];
//構(gòu)建播放器對(duì)象
self.myPlayer = [AVPlayer playerWithPlayerItem:self.item];
//構(gòu)建播放器的layer
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.myPlayer];
self.playerLayer.frame = CGRectMake(0, 66, self.view.bounds.size.width, 300);
[self.view.layer addSublayer:self.playerLayer];
//通過KVO來觀察status屬性的變化,來獲得播放之前的錯(cuò)誤信息
[self.item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
}
KVO的回調(diào)方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:
(NSDictionary<NSString *,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"status"]) {
//取出status的新值
AVPlayerItemStatus status = [change[NSKeyValueChangeNewKey]intValue];
switch (status) {
case AVPlayerItemStatusFailed:
NSLog(@"item 有誤");
self.isReadToPlay = NO;
break;
case AVPlayerItemStatusReadyToPlay:
NSLog(@"準(zhǔn)好播放了");
self.isReadToPlay = YES;
self.avSlider.maximumValue = self.item.duration.value / self.item.duration.timescale;
break;
case AVPlayerItemStatusUnknown:
NSLog(@"視頻資源出現(xiàn)未知錯(cuò)誤");
self.isReadToPlay = NO;
break;
default:
break;
}
}
//移除監(jiān)聽(觀察者)
[object removeObserver:self forKeyPath:@"status"];
}
視頻的播放按鈕
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(250, 600, 100, 100);
button.backgroundColor = [UIColor redColor];
[button setTitle:@"按鈕" forState:UIControlStateNormal];
[button addTarget:self action:@selector(playAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
button的回調(diào)方法
- (void)playAction{
if ( self.isReadToPlay) {
[self.myPlayer play];
}else{
NSLog(@"視頻正在加載中");
}
}
創(chuàng)建一個(gè)進(jìn)度條來控制視頻的進(jìn)度
使用懶加載的方式,將進(jìn)度條添加到View上面
- (UISlider *)avSlider{
if (!_avSlider) {
_avSlider = [[UISlider alloc]initWithFrame:CGRectMake(0, 55, self.view.bounds.size.width, 30)];
[self.view addSubview:_avSlider];
}return _avSlider;
}
在viewDidLoad中個(gè)slider(進(jìn)度條)添加一個(gè)回調(diào)。
[self.avSlider addTarget:self action:@selector(avSliderAction) forControlEvents:
UIControlEventTouchUpInside|UIControlEventTouchCancel|UIControlEventTouchUpOutside];
回調(diào)方法
- (void)avSliderAction{
//slider的value值為視頻的時(shí)間
float seconds = self.avSlider.value;
//讓視頻從指定的CMTime對(duì)象處播放。
CMTime startTime = CMTimeMakeWithSeconds(seconds, self.item.currentTime.timescale);
//讓視頻從指定處播放
[self.myPlayer seekToTime:startTime completionHandler:^(BOOL finished) {
if (finished) {
[self playAction];
}
}];
}
以上就是實(shí)現(xiàn)一個(gè)視頻的播放和快進(jìn)快退的方法與步驟。