AVPlayer
AVPlayer播放器存在于AVFoundation中, 能夠播放網(wǎng)絡(luò)和本地視頻/音頻, 和MediaPlayer.framework框架下的兩個(gè)播放器不同, 并沒(méi)有默認(rèn)的UI界面,是一個(gè)高度自定義的播放器廉邑。與AVAudioPlayer相比,哥蔚,AVPlayer可以實(shí)現(xiàn)流媒體播放,而AVAudioPlayer只能緩存完再播放蛛蒙。
AVPlayer實(shí)現(xiàn)
AVPlayer通過(guò)asset來(lái)初始化player糙箍,當(dāng)然也可以直接用URL初始化
NSURL *musicURL = [self.tracksVM playURLForRow:_indexPathRow];
AVPlayerItem *currentPlayerItem = [AVPlayerItem playerItemWithURL:musicURL];
_player = [[AVPlayer alloc] initWithPlayerItem:currentPlayerItem];
如果要使用視頻播放,需要再添加AVPlayerLayer
//設(shè)置播放頁(yè)面
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:_player];
layer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 300);
layer.backgroundColor = [UIColor cyanColor].CGColor;
//設(shè)置播放窗口和當(dāng)前視圖之間的比例顯示內(nèi)容
layer.videoGravity = AVLayerVideoGravityResizeAspect;
//添加到self.view
[self.view.layer addSublayer:layer];
AVPlayerLayer常用操作
[self.player play];//播放
[self.player pause];//暫停
[self.player seekToTime:CMTimeMake(0, 1)];//改變進(jìn)度
[self.player.currentItem currentTime]//當(dāng)前時(shí)間
[self.player.currentItem duration]//總時(shí)間
self.player.volume = 1.0f;//設(shè)置音量
當(dāng)切換上下首時(shí)使用replaceCurrentItemWithPlayerItem方法牵祟,可以切換item深夯,但是發(fā)現(xiàn)切換時(shí)會(huì)造成卡頓,后來(lái)使用initWithPlayerItem替代解決
[self.player replaceCurrentItemWithPlayerItem:_currentPlayerItem];//切換item
監(jiān)聽(tīng)AVPlayer
通過(guò)addPeriodicTimeObserverForInterval:監(jiān)聽(tīng)進(jìn)度變化诺苹,interval參數(shù)為響應(yīng)的間隔時(shí)間塌西,這里設(shè)為每秒都響應(yīng),queue是隊(duì)列筝尾,傳NULL代表在主線程執(zhí)行捡需。并且可以更新UI,比如進(jìn)度條的當(dāng)前時(shí)間與音頻總長(zhǎng)度筹淫。
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)
監(jiān)聽(tīng)AVPlayer是否播放完成站辉,完成后按照當(dāng)前狀態(tài)執(zhí)行操作
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.player currentItem]];
-(void)playbackFinished:(NSNotification *)notification{
if (_cycle == theSong) {
[self playAgain];
}else if(_cycle == nextSong){
[self playNextMusic];
}else if(_cycle == isRandom){
[self randomMusic];
}
NSLog(@"開(kāi)始下一首");
[self.delegate changeMusic];
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[@"coverURL"] = [self.tracksVM coverURLForRow:_indexPathRow];
[[NSNotificationCenter defaultCenter] postNotificationName:@"changeCoverURL" object:nil userInfo:userInfo];
}
設(shè)置后臺(tái)播放,與鎖屏?xí)r展示歌曲信息控制播放
// 支持后臺(tái)播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
// 激活
[[AVAudioSession sharedInstance] setActive:YES error:nil];
// 開(kāi)始監(jiān)控
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
// 播放信息中心
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
// 初始化播放信息
NSMutableDictionary *info = [NSMutableDictionary dictionary];
// 專輯名稱
info[MPMediaItemPropertyAlbumTitle] = [self playMusicName];
// 歌手
info[MPMediaItemPropertyArtist] = [self playSinger];
// 歌曲名稱
info[MPMediaItemPropertyTitle] = [self playMusicTitle];
// 設(shè)置圖片
info[MPMediaItemPropertyArtwork] = [[MPMediaItemArtwork alloc] initWithImage:[self playCoverImage]];
// 設(shè)置持續(xù)時(shí)間(歌曲的總時(shí)間)
[info setObject:[NSNumber numberWithFloat:CMTimeGetSeconds([self.player.currentItem duration])] forKey:MPMediaItemPropertyPlaybackDuration];
// 設(shè)置當(dāng)前播放進(jìn)度
[info setObject:[NSNumber numberWithFloat:CMTimeGetSeconds([self.player.currentItem currentTime])] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
// 切換播放信息
center.nowPlayingInfo = info;
遠(yuǎn)程控制事件 Remote Control Event可以在不打開(kāi)app時(shí)损姜,控制音樂(lè)播放器播放
// 成為第一響應(yīng)者(必備條件)
[self becomeFirstResponder];
#pragma mark - 遠(yuǎn)程控制事件監(jiān)聽(tīng)
- (BOOL)canBecomeFirstResponder{
return YES;
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)event{
// event.type; // 事件類型
// event.subtype; // 事件的子類型
// UIEventSubtypeRemoteControlPlay = 100,
// UIEventSubtypeRemoteControlPause = 101,
// UIEventSubtypeRemoteControlStop = 102,
// UIEventSubtypeRemoteControlTogglePlayPause = 103,
// UIEventSubtypeRemoteControlNextTrack = 104,
// UIEventSubtypeRemoteControlPreviousTrack = 105,
// UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
// UIEventSubtypeRemoteControlEndSeekingBackward = 107,
// UIEventSubtypeRemoteControlBeginSeekingForward = 108,
// UIEventSubtypeRemoteControlEndSeekingForward = 109,
switch (event.subtype) {
case UIEventSubtypeRemoteControlPlay:
case UIEventSubtypeRemoteControlPause:
[[FYPlayManager sharedInstance] pauseMusic];
break;
case UIEventSubtypeRemoteControlNextTrack:
[[FYPlayManager sharedInstance] nextMusic];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
[[FYPlayManager sharedInstance] previousMusic];
default:
break;
}
}
AVPlayerLayer是流媒體播放饰剥,如果要實(shí)現(xiàn)邊下邊緩存,緩存完成下載好文件的話摧阅,需要自定義scheme來(lái)創(chuàng)建avplayer汰蓉,在資源的 URL 不能被系統(tǒng)識(shí)別時(shí)會(huì)自定義視頻加載,從而使用AVAssetResourceLoaderDelegate