iOS AVPlayer播放mp3

Posted 火海夕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS AVPlayer播放mp3相关的知识,希望对你有一定的参考价值。

**注释: [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 监听方法中,不然音频没有加载完成是无法播放的

以上是关于iOS AVPlayer播放mp3的主要内容,如果未能解决你的问题,请参考以下文章

iOS AVPlayer播放mp3

迅速。在模拟器上播放良好的 mp3 文件,但在设备上播放时没有音量。 AVPlayer

在 iOS 中播放 Avplayer 时移动滑块变得跳跃

无法通过 AVPlayer 通过 HTTP 播放 mp3 文件

AVPlayer 加载缓慢

本地文件使用 AVAudioPlayer 播放,但不使用 AVPlayer?