AVPlayer 播放 使用 封装

由于本人学识尚浅如有不对请大神加以指正。


本文主要讲解AVPlayer的基本使用和简单封装,主要使用AVPlayer做音乐播放。

AVPlayer在使用之前应了解:

AVPlayer 的rate属性 这个属性表示AVPlayer的播放状态 0暂停 1播放

AVPlayerItem 媒体资源管理对象,每个AVPlayerItem对应一个视频或音频资源

AVPlayerItemStatus 视频音频播放状态

typedef NS_ENUM(NSInteger, AVPlayerItemStatus) {

AVPlayerItemStatusUnknown,未知资源

AVPlayerItemStatusReadyToPlay,准备播放

AVPlayerItemStatusFailed 加载失败

};

AVPlayerItem 的播放完成通知

AVPlayerItemDidPlayToEndTimeNotification

AVPlayer 监控播放时间的方法 用于更新进度条

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

AVPlayer 设置播放时间

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



播放音乐

//播放网络音乐

AVPlayerItem *playerItem;

NSURL *url=[NSURL URLWithString:"音乐链接字符串"];

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

//播放项目中的音乐

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];

以上就是音乐的播放了


现在讲解对AVPlayer的简单封装

MusicManger.h

首先引入AVFoundation框架

#import<AVFoundation/AVFoundation.h>

自己的音乐实体类

#import "Music.h"

设置代理协议

@protocol MusicMangerDelegate <NSObject>

@optional

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

-(void)updateBufferProgress:(NSTimeInterval)progress;

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

@end

设置功能函数

@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;

}

}

//播放当前音乐

-(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

{

//监控AVPlayer的status属性获得播放状态

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

//监控缓冲加载情况属性获取缓冲情况

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

//AVPlayerTimeControlStatus

//监控播放完成通知

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

//监控当前播放时间

__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];

}

}];

}


//播放完成自动播放下一曲

-(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的实现和代理的实现


//KVO观察属性变化

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

{

AVPlayerItem *playerItem=object;

//播放状态

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

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

switch (status) {

//资源加载成功

case AVPlayerItemStatusReadyToPlay:

{

[self.player play];

}

break;

case AVPlayerItemStatusFailed:

{

NSLog(@"加载失败,播放出错");

}

break;

case AVPlayerItemStatusUnknown:

{

NSLog(@"未知资源播放错误");

}

break;

default:

break;

}

}


//缓冲时间

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:)])

{

//将缓冲时间通过代理传出去

[self.delegate updateBufferProgress:totalBuffer];

}

}

//音乐对象的变化

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];

}

}

//当前音乐的播放状态

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

{

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

NSLog(@"%@",rate);

//利用通知中心将当前播放状态传出去

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

}

}


最后感谢大家能看到最后

demo的话以后会上传

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

推荐阅读更多精彩内容