// // PBAVPlayerManager.m // IphoneBIMe // // Created by zjf on 2019/1/3. // Copyright © 2019 ProBIM. All rights reserved. // #import "PBAVPlayerManager.h" @interface PBAVPlayerManager() @property (nonatomic, strong) AVPlayer *player; @property (nonatomic, strong) AVPlayerItem *item; @end @implementation PBAVPlayerManager + (instancetype)sharedManager{ static PBAVPlayerManager *manager; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[PBAVPlayerManager alloc] init]; }); return manager; } - (instancetype)init { self = [super init]; if (self) { _player = [[AVPlayer alloc] init]; } return self; } #pragma mark - 播放本地录音 - (void)playItemWithName:(NSString *)recodingName { if (recodingName != nil) { //真机必须添加此代码 AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; NSURL *sourceMovieUrl = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:recodingName]]; AVAsset *movieAsset = [AVURLAsset URLAssetWithURL:sourceMovieUrl options:nil]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:movieAsset]; if (self.item) { [self removeObserverFromPlayerItem:self.item]; [_player replaceCurrentItemWithPlayerItem:playerItem]; }else { _player = [AVPlayer playerWithPlayerItem:playerItem]; } self.item = playerItem; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem]; [self addObserverToPlayerItem:self.item]; [_player play]; }else { [YJProgressHUD showMessage:@"没有找到此音频文件" inView:nil]; } } #pragma mark - 播放网络音频 - (void)playItemWithUrl:(NSString *)recordingUrl { AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; // NSURL *sourceMovieUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",BaseUrl,recordingUrl]]; NSURL *sourceMovieUrl = [NSURL URLWithString:recordingUrl]; AVAsset *movieAsset = [AVURLAsset URLAssetWithURL:sourceMovieUrl options:nil]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:movieAsset]; if (self.item) { [self removeObserverFromPlayerItem:self.item]; [_player replaceCurrentItemWithPlayerItem:playerItem]; } else { _player = [AVPlayer playerWithPlayerItem:playerItem]; } self.item = playerItem; [_player replaceCurrentItemWithPlayerItem:playerItem]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem]; [self addObserverToPlayerItem:self.item]; [_player play]; } /** * 给AVPlayerItem添加监控 * * @param playerItem AVPlayerItem对象 */ - (void)addObserverToPlayerItem:(AVPlayerItem *)playerItem { if (playerItem) { [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; //监控网络加载情况属性 [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; //给AVPlayerItem添加播放完成通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem]; } } - (void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem { if (playerItem) { [playerItem removeObserver:self forKeyPath:@"status"]; [playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"]; [[NSNotificationCenter defaultCenter]removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { AVPlayerItem *playerItem = object; if ([keyPath isEqualToString:@"status"]) { AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; switch (status) { case AVPlayerStatusUnknown:{ self.status = ETPlayer_UnkonwError; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_UnkonwError]; } break; } case AVPlayerStatusReadyToPlay:{ self.status = ETPlayer_ReadyToPlay; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_ReadyToPlay]; } CMTime time = _player.currentItem.duration; float value1 = time.value / time.timescale; float value2 = CMTimeGetSeconds(self.player.currentItem.asset.duration); NSLog(@"正在播放,_player.currentItem.duration 总长度:%.2f", value1); NSLog(@"正在播放,_player.currentItem.asset.duration总长度:%.2f", value2); break; } case AVPlayerStatusFailed: { self.status = ETPlayer_PlayFailed; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_PlayFailed]; } [PBNoteCenter postNotificationName:PBNoteCenterPlayOver object:nil]; [YJProgressHUD showMessage:@"加载音频失败" inView:nil]; break; } default: break; } }else if([keyPath isEqualToString:@"loadedTimeRanges"]) { double timeInterval = [self availableDuration]; CMTime duration = playerItem.duration; double totalDuration = CMTimeGetSeconds(duration); NSLog(@"timeInterval:%f",timeInterval); NSLog(@"totalDuration:%f",totalDuration); if (timeInterval < 1.5 * totalDuration) { self.status = ETPlayer_Loading; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_Loading]; } }else if ([self isPlaying]) { self.status = ETPlayer_Playing; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_Playing]; } } else { self.status = ETPlayer_Loading; if ([self respondsDelegate]) { [self.delegate currentPlayerStatus:ETPlayer_Loading]; } } } } - (BOOL)respondsDelegate { if (self.delegate && [self.delegate respondsToSelector:@selector(currentPlayerStatus:)]) { return YES; } return NO; } - (BOOL)isPlaying { // 可以根据值去判断播放还是暂停 if (_player.rate == 0.0) { return NO; } return YES; } - (double)availableDuration{ NSArray *loadedTimeRanges = self.player.currentItem.loadedTimeRanges; NSValue *value = loadedTimeRanges.firstObject; CMTimeRange timeRange = value.CMTimeRangeValue; double startSeconds = CMTimeGetSeconds(timeRange.duration); double durationSeconds = CMTimeGetSeconds(timeRange.duration); return startSeconds + durationSeconds; } - (void)playbackFinished:(NSNotification *)noti { [PBNoteCenter postNotificationName:PBNoteCenterPlayOver object:nil]; } - (void)stopPlay { [_player pause]; } @end