AVPlayer 播放 使用 封裝

由于本人學(xué)識(shí)尚淺如有不對(duì)請(qǐng)大神加以指正。


本文主要講解AVPlayer的基本使用和簡單封裝尘颓,主要使用AVPlayer做音樂播放公给。

AVPlayer在使用之前應(yīng)了解:

AVPlayer 的rate屬性 這個(gè)屬性表示AVPlayer的播放狀態(tài) 0暫停 1播放

AVPlayerItem 媒體資源管理對(duì)象,每個(gè)AVPlayerItem對(duì)應(yīng)一個(gè)視頻或音頻資源

AVPlayerItemStatus 視頻音頻播放狀態(tài)

typedef NS_ENUM(NSInteger, AVPlayerItemStatus) {

AVPlayerItemStatusUnknown,未知資源

AVPlayerItemStatusReadyToPlay,準(zhǔn)備播放

AVPlayerItemStatusFailed 加載失敗

};

AVPlayerItem 的播放完成通知

AVPlayerItemDidPlayToEndTimeNotification

AVPlayer 監(jiān)控播放時(shí)間的方法 用于更新進(jìn)度條

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

AVPlayer 設(shè)置播放時(shí)間

- (void)seekToTime:(CMTime)time completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0);



播放音樂

//播放網(wǎng)絡(luò)音樂

AVPlayerItem *playerItem姚糊;

NSURL *url=[NSURL URLWithString:"音樂鏈接字符串"];

playerItem=[[AVPlayerItem alloc]initWithURL:url];

//播放項(xiàng)目中的音樂

NSString *audioPath = [[NSBundle mainBundle] pathForResource:@"音樂名" ofType:@"格式"];

NSURl *audioUrl = [NSURL fileURLWithPath:audioPath];

playerItem=[[AVPlayerItem alloc]initWithURL:audioUrl];

//播放下載在document中的音樂

NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString *fullPath=[documentsDirectory stringByAppendingPathComponent:fileName];

NSURL *musicUrl=[NSURL fileURLWithPath:fullPath];

playerItem=[[AVPlayerItem alloc]initWithURL:url];

以上就是音樂的播放了


現(xiàn)在講解對(duì)AVPlayer的簡單封裝

MusicManger.h

首先引入AVFoundation框架

#import<AVFoundation/AVFoundation.h>

自己的音樂實(shí)體類

#import "Music.h"

設(shè)置代理協(xié)議

@protocol MusicMangerDelegate <NSObject>

@optional

-(void)updateProgressByCurrentTime:(float)currentPlayTime totalTime:(float)totalTime timeStr:(NSString *)str;

-(void)updateBufferProgress:(NSTimeInterval)progress;

-(void)updateCurrentMusic:(Music *)aMusic;

@end

設(shè)置功能函數(shù)

@interface MusicManager : NSObject

@property (weak,nonatomic) id<MusicMangerDelegate>delegate;

+(instancetype)defaultManager;

-(void)playMusic:(Music *)aMusic musicArray:(NSArray *)array index:(NSInteger)index;

-(void)playerProgressChanged:(float)currentProgress;

-(BOOL)play;

-(void)pause;

-(void)playNext;

-(void)playPrevious;

@end


MusicManger.m

#import "MusicManager.h"

@interface MusicManager ()

@property (strong,nonatomic) AVPlayer *player;

@property (strong,nonatomic) NSTimer *timer;

@property (strong,nonatomic) Music *aMusic;

@property (strong,nonatomic) NSArray *musicArray;

@property (assign,nonatomic) NSInteger index;

@end

@implementation MusicManager

//AVPlayer懶加載

-(AVPlayer *)player

{

if(_player==nil)

{

_player=[[AVPlayer alloc]init];

[_player addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

}

return _player;

}

//程序的入口

-(void)playMusic:(Music *)aMusic musicArray:(NSArray *)array index:(NSInteger)index

{

if (aMusic&&array!=nil&&index>=0) {

self.musicArray=array;

self.index=index;

[self addObserver:self forKeyPath:@"aMusic" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

[self playCurrentMusic:aMusic];

}else

{

NSLog(@"未傳入aMusic或musicList或index");

return;

}

}

//播放當(dāng)前音樂

-(void)playCurrentMusic:(Music *)aMusic

{

static Music *theMusic;

if (theMusic==aMusic) {

return;

}else{

AVPlayerItem *playerItem遏弱;

NSString *urlStr=[NSString stringWithFormat:@"%@",aMusic.musicLink];

NSString *encodingStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSURL *url=[NSURL URLWithString:encodingStr];

playerItem=[[AVPlayerItem alloc]initWithURL:url];

//播放前移除playerItem的系列觀察者

[self currentItemRemoveObserver];

[self.player replaceCurrentItemWithPlayerItem:playerItem];

//為playerItem添加觀察者

[self currentItemAddObserver];

theMusic=aMusic;

}

-(void)currentItemAddObserver

{

//監(jiān)控AVPlayer的status屬性獲得播放狀態(tài)

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

//監(jiān)控緩沖加載情況屬性獲取緩沖情況

[self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

//AVPlayerTimeControlStatus

//監(jiān)控播放完成通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

//監(jiān)控當(dāng)前播放時(shí)間

__weak typeof (self) WeakSelf=self;

_timer=[_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 5) queue:dispatch_get_main_queue() usingBlock:^(CMTime time)

{

float currentTime = WeakSelf.player.currentItem.currentTime.value/WeakSelf.player.currentItem.currentTime.timescale;

float duration=CMTimeGetSeconds(WeakSelf.player.currentItem.duration);

NSString *timeStr=[WeakSelf timeStringFromSecond:currentTime];

if (self.delegate&&[self.delegate respondsToSelector:@selector(updateProgressByCurrentTime:totalTime:timeStr:)])

{

//將獲得的音樂信息通過代理傳出去

[WeakSelf.delegate updateProgressByCurrentTime:currentTime totalTime:duration timeStr:timeStr];

}

}];

}


//播放完成自動(dòng)播放下一曲

-(void)playNext

{

if (self.index==self.musicArray.count-1) {

self.index=0;

}else

{

self.index++;

}

self.aMusic=self.musicArray[self.index];

[self playCurrentMusic:self.aMusic];

}


//移除playItem的觀察者

-(void)currentItemRemoveObserver

{

[self.player.currentItem removeObserver:self forKeyPath:@"status"];

[self.player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"];

[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

[self.player removeTimeObserver:_timer];

}


//播放音樂

-(BOOL)play

{

if (self.player.status==AVPlayerStatusReadyToPlay) {

[self.player play];

return YES;

}

return NO;

}

//暫停播放

-(void)pause

{

[self.player pause];

}

//播放下一曲

-(void)playNext

{

if (self.index==self.musicArray.count-1) {

self.index=0;

}else

{

self.index++;

}

self.aMusic=self.musicArray[self.index];

[self playCurrentMusic:self.aMusic];

}

//播放上一曲

-(void)playPrevious

{

if (self.index==0) {

self.index=self.musicArray.count-1;

}else

{

self.index--;

}

self.aMusic=self.musicArray[self.index];

[self playCurrentMusic:self.aMusic];

}


這里KVO的實(shí)現(xiàn)和代理的實(shí)現(xiàn)


//KVO觀察屬性變化

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context

{

AVPlayerItem *playerItem=object;

//播放狀態(tài)

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

AVPlayerItemStatus status=[change[@"new"]integerValue];

switch (status) {

//資源加載成功

case AVPlayerItemStatusReadyToPlay:

{

[self.player play];

}

break;

case AVPlayerItemStatusFailed:

{

NSLog(@"加載失敗,播放出錯(cuò)");

}

break;

case AVPlayerItemStatusUnknown:

{

NSLog(@"未知資源播放錯(cuò)誤");

}

break;

default:

break;

}

}


//緩沖時(shí)間

else if([keyPath isEqualToString:@"loadedTimeRanges"])

{

NSArray *bufferArray=playerItem.loadedTimeRanges

;

CMTimeRange timeRange=[bufferArray.firstObject CMTimeRangeValue];

float startSeconds=CMTimeGetSeconds(timeRange.start);

float durationSeconds=CMTimeGetSeconds(timeRange.duration);

NSTimeInterval totalBuffer=startSeconds+durationSeconds;

NSLog(@"共緩沖:%.2f",totalBuffer);

if(self.delegate&&[self.delegate respondsToSelector:@selector(updateBufferProgress:)])

{

//將緩沖時(shí)間通過代理傳出去

[self.delegate updateBufferProgress:totalBuffer];

}

}

//音樂對(duì)象的變化

else if ([keyPath isEqualToString:@"aMusic"])

{

Music *currentMusic=change[@"new"];

[[NSNotificationCenter defaultCenter]postNotificationName:@"currentMusic" object:currentMusic];

if (self.delegate&&[self.delegate respondsToSelector:@selector(updateCurrentMusic:)]) {

[self.delegate updateCurrentMusic:currentMusic];

}

}

//當(dāng)前音樂的播放狀態(tài)

else if ([keyPath isEqualToString:@"rate"])

{

NSString *rate=change[@"new"];

NSLog(@"%@",rate);

//利用通知中心將當(dāng)前播放狀態(tài)傳出去

[[NSNotificationCenter defaultCenter]postNotificationName:@"isPlaying" object:rate];

}

}


最后感謝大家能看到最后

demo的話以后會(huì)上傳

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市补憾,隨后出現(xiàn)的幾起案子漫萄,更是在濱河造成了極大的恐慌,老刑警劉巖盈匾,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腾务,死亡現(xiàn)場離奇詭異,居然都是意外死亡削饵,警方通過查閱死者的電腦和手機(jī)岩瘦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窿撬,“玉大人启昧,你說我怎么就攤上這事∨椋” “怎么了密末?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我严里,道長新啼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任刹碾,我火速辦了婚禮燥撞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迷帜。我一直安慰自己物舒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布戏锹。 她就那樣靜靜地躺著冠胯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪景用。 梳的紋絲不亂的頭發(fā)上涵叮,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音伞插,去河邊找鬼。 笑死盾碗,一個(gè)胖子當(dāng)著我的面吹牛媚污,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播廷雅,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耗美,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了航缀?” 一聲冷哼從身側(cè)響起商架,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芥玉,沒想到半個(gè)月后蛇摸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灿巧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年赶袄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抠藕。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饿肺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盾似,到底是詐尸還是另有隱情敬辣,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站溉跃,受9級(jí)特大地震影響汰聋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喊积,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一烹困、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乾吻,春花似錦髓梅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诡必,卻和暖如春奢方,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爸舒。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蟋字, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扭勉。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓鹊奖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涂炎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忠聚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容