**注释: [self.player play];一定要写在- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> )change context:(void )context 监听方法中,不然音频没有加载完成是无法播放的
//
// TFPlayMusicManager.m
// iOS-TutorTeacher
//
// Created by kent J on 2017/6/28.
// Copyright © 2017年 aizhikang. All rights reserved.
//
#import "TFPlayMusicManager.h"
static TFPlayMusicManager *playerManager = nil;
@implementation TFPlayMusicManager
#pragma mark - Private
+(TFPlayMusicManager *)defaultManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
playerManager = [[self alloc] init];
});
return playerManager;
}
// 当前是否正在录音
+(BOOL)isPlaying{
return [[TFPlayMusicManager defaultManager] isPlaying];
}
-(BOOL)isPlaying{
return !!_player;
}
// 播放
+ (void)asyncPlayMusicWithPreparePath:(NSString *)musicUrl
completion:(void(^)(NSError *error))completion{
[TFPlayMusicManager asyncPlayMusicWithPreparePath:musicUrl completion:completion];
}
// 停止播放
+(void)asyncStopMusicWithCompletion:(void(^)(NSString *recordPath))completion{
[TFPlayMusicManager asyncStopMusicWithCompletion:completion];
}
// 取消录音
+(void)cancelCurrentRecording{
[[TFPlayMusicManager defaultManager] cancelCurrentRecording];
}
// 取消录音
- (void)cancelCurrentRecording
{
}
+(AVPlayer *)recorder{
return [TFPlayMusicManager defaultManager].player;
}
// 开始播放,文件放到musicUrl下
- (void)asyncPlayMusicWithPreparePath:(NSString *)musicUrl
completion:(void(^)(NSError *error))completion
{
__weak TFPlayMusicManager *weakSelf = self;
NSURL * url = [NSURL URLWithString:musicUrl];
self.playItem = [[AVPlayerItem alloc]initWithURL:url];
self.player = [[AVPlayer alloc]initWithPlayerItem:self.playItem];
self.playItem = self.player.currentItem;
self.player.automaticallyWaitsToMinimizeStalling = NO;
[self.playItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[self.playItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
//添加播放进度观察者
self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
float total = CMTimeGetSeconds(weakSelf.playItem.duration);
if (current) {
weakSelf.progress = current / total;
weakSelf.playTime = [NSString stringWithFormat:@"%.f",current];
weakSelf.playDuration = [NSString stringWithFormat:@"%.2f",total];
}
DebugLog(@"progress = %f playTime = %@ playDuration = %@",weakSelf.progress,weakSelf.playTime,weakSelf.playDuration);
}];
// completion(completion);
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
/*
AVPlayerTimeControlStatusPaused,
AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate,
AVPlayerTimeControlStatusPlaying
*/
if ([keyPath isEqualToString:@"status"]) {
switch (self.player.status) {
case AVPlayerStatusUnknown:
DebugLog(@"KVO:未知状态,此时不能播放");
break;
case AVPlayerStatusReadyToPlay:
// self.status = AVPlayerStatusReadyToPlay;
{
if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
}
DebugLog(@"KVO:准备完毕,可以播放 %ld++++++%@",(long)self.player.timeControlStatus,self.player.reasonForWaitingToPlay);
[self.player play];
}
break;
case AVPlayerStatusFailed:
DebugLog(@"KVO:加载失败,网络或者服务器出现问题");
break;
default:
break;
}
}
if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSArray * array = self.playItem.loadedTimeRanges;
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue]; //本次缓冲的时间范围
NSTimeInterval totalBuffer = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration); //缓冲总长度
DebugLog(@"共缓冲%.2f",totalBuffer);
}
}
//移除观察者
-(void)removeObserver{
// [self.playItem removeObserver:self forKeyPath:@"status"];
if (_timeObserve) {
[_player removeTimeObserver:_timeObserve];
_timeObserve = nil;
}
}
// 停止录音
-(void)asyncStopMusicWithCompletion:(void(^)(NSString *recordPath))completion{
playFinish = completion;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self->_player pause];
});
}
#pragma mark - getter
- (NSDictionary *)recordSetting
{
if (!_musicSetting) {
_musicSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithFloat: 11025.0],AVSampleRateKey, //采样率
[NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采样位数 默认 16
[NSNumber numberWithInt: 2], AVNumberOfChannelsKey,//通道的数目
AVAudioQualityMin, AVEncoderAudioQualityKey,//通道的数目
nil];
}
return _musicSetting;
}
-(instancetype)init{
if (self = [super init]) {
}
return self;
}
-(void)dealloc{
DebugLog(@"内存释放");
}
@end
**注释: [self.player play];一定要写在- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> )change context:(void )context 监听方法中,不然音频没有加载完成是无法播放的