由于本人学识尚浅如有不对请大神加以指正。
本文主要讲解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的话以后会上传