AVAudioPlayer、AVPlayer和AVQueuePlayer的使用

AVAudioPlayer 簡述

AVAudioPlayer是屬于 AVFundation.framework 的一個類,它的功能類似于一個功能強大的播放器丢习,AVAudioPlayer每次播放都需要將上一個player對象釋放掉,然后重新創(chuàng)建一個player來進行播放,AVAudioPlayer 支持廣泛的音頻格式淮悼,主要是以下這些格式咐低。

  • ACC
  • AMR(Adaptive multi-Rate,一種語音格式)
  • ALAC (Apple lossless Audio Codec)
  • iLBC (internet Low Bitrate Codec袜腥,另一種語音格式)
  • IMA4 (IMA/ADPCM)
  • linearPCM (uncompressed)
  • u-law 和 a-law
  • MP3 (MPEG-Laudio Layer 3)

AVAudioPlayer 使用

AVAudioPlayer 初始化
 1. initWithContentsOfURL: error: 從URL加載音頻见擦,返回 AVAudioPlayer 對象
 2. initWithData: error: 加載NSdata對象的音頻文件,返回 AVAudioPlayer 對象
AVAudioPlayer 方法調用
 //準備播放 可以判斷player創(chuàng)建成功之后調用羹令,調用[player play]則可以節(jié)省播放之前的間隔時間鲤屡。
- (BOOL)prepareToPlay;
//異步播放
- (BOOL)play; 
//在某個時間點播放
- (BOOL)playAtTime:(NSTimeInterval)time NS_AVAILABLE(10_7, 4_0); 
//暫停播放,但仍然可以播放
- (void)pause; 
//停止播放福侈,不再準備播放了
- (void)stop; 
//更新音頻測量值酒来,注意如果要更新音頻測量值必須設置meteringEnabled為YES,通過音頻測量值可以即時獲得音頻分貝等信息
- (void)updateMeters; 
//返回給定通道的分貝峰值功率
- (float)peakPowerForChannel:(NSUInteger)channelNumber; 
//獲得指定聲道的分貝峰值肪凛,注意如果要獲得分貝峰值必須在此之前調用updateMeters方法
- (float)averagePowerForChannel:(NSUInteger)channelNumber;
AVAudioPlayer 屬性設置
playing //播放器是否正在播放 獲取通過isPlaying
numberOfChannels //該音頻的聲道次數役首,只讀
duration //該音頻播放時長
url //音頻文件路徑, 只讀
data //音頻數據,只讀
pan NS_AVAILABLE(10_7, 4_0) //立體聲設置 設為 -1.0 則左邊播放 設為 0.0 則中央播放 設為 1.0 則右邊播放
enableRate NS_AVAILABLE(10_8, 5_0);  //是否允許改變播放速率
rate NS_AVAILABLE(10_8, 5_0); //播放速率 0.5 (半速播放) ~ 2.0(倍速播放) 注1.0 是正常速度
currentTime //該音頻的播放點
deviceCurrentTime //輸出設備播放音頻的時間显拜,注意如果播放中被暫停此時間也會繼續(xù)累加
numberOfLoops  //循環(huán)次數,如果要單曲循環(huán)爹袁,設置為負數
volume //播放器的音頻增益远荠,值:0.0~1.0
channelAssignments //獲得或設置播放聲道
AVAudioPlayer 代理方法
//音頻播放完成
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
//音頻解碼發(fā)生錯誤
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error
//如果音頻被中斷,比如有電話呼入失息,該方法就會被回調譬淳,該方法可以保存當前播放信息,以便恢復繼續(xù)播放的進度
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player

AVPlayer 簡述

AVPlayer支持播放本地盹兢、分步下載邻梆、或在線流媒體音視頻,不僅可以播放音頻绎秒,配合AVPlayerLayer類可實現視頻播放浦妄。另外支持播放進度監(jiān)聽。
AVPlayer只支持單個媒體資源播放。

AVPlayer需要配合AVPlayerItem關聯來進行媒體播放剂娄。

AVPlayer 使用

AVPlayer 初始化
//類方法蠢涝,從url加載音頻
+ (instancetype)playerWithURL:(NSURL *)URL
//類方法,配合AVPlayerItem使用
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item
//實例方法阅懦,從url加載音頻
- (instancetype)initWithURL:(NSURL *)URL
//實例方法和二,配合AVPlayerItem使用
- (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item
AVPlayer KVO添加監(jiān)聽

1.播放狀態(tài)改變監(jiān)聽

//KVO監(jiān)聽播放狀態(tài)
[self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

處理KVO回調事件

//處理KVO回調事件
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        switch (self.player.status) {
            case AVPlayerStatusUnknown:
                NSLog(@"未知轉態(tài)");
                break;
            case AVPlayerStatusReadyToPlay:
                NSLog(@"準備播放");
                break;
            case AVPlayerStatusFailed:
                NSLog(@"加載失敗");
                break;
                
            default:
                break;
        }
    }
}

2.KVO監(jiān)聽音樂緩沖狀態(tài)

//KVO監(jiān)聽音樂緩沖狀態(tài)
[self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];

處理KVO回調事件

//處理KVO回調事件
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        
        NSArray *timeRanges = self.player.currentItem.loadedTimeRanges;
        //本次緩沖的時間范圍
        CMTimeRange timeRange = [timeRanges.firstObject CMTimeRangeValue];
        //緩沖總長度
        NSTimeInterval totalLoadTime = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration);
        //音樂的總時間
        NSTimeInterval duration = CMTimeGetSeconds(self.player.currentItem.duration);
        //計算緩沖百分比例
        NSTimeInterval scale = totalLoadTime/duration;
        NSLog(@"---%f,---%f,---%f",totalLoadTime,duration,scale);
        //更新緩沖進度條
        //        self.loadProgress.progress = scale;
        
    }
}
  1. 播放結束事件的監(jiān)聽
//播放結束事件的監(jiān)聽
[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playFinied:) name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:self.player.currentItem];

處理KVO回調事件

//播放結束回調
- (void)playFinied:(AVPlayerItem *)item {
    NSLog(@"播放結束");
    self.slider.value = 0;
}
  1. 開始播放時,通過AVPlayer的方法監(jiān)聽播放進度耳胎,并更新進度條(定期監(jiān)聽的方法)
//開始播放時惯吕,通過AVPlayer的方法監(jiān)聽播放進度,并更新進度條(定期監(jiān)聽的方法)
__weak typeof(self) weakSelf = self;
    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        //當前播放的時間
        float current = CMTimeGetSeconds(time);
        //總時間
        float total = CMTimeGetSeconds(item.duration);
        if (current) {
            float progress = current / total;
            //更新播放進度條
            weakSelf.slider.value = progress;
        }
    }];
  1. 拖動進度條改變播放進度
//拖動進度條改變播放進度
- (void)playValueChange:(UISlider *)sender {
    //計算時間
    float time = sender.value * CMTimeGetSeconds(self.player.currentItem.duration);
    //跳到當前指定時間
    [self.player seekToTime:CMTimeMake(time, 1)];
}

AVQueuePlayer 簡述

AVPlayer只支持單個媒體資源的播放怕午,我們可以使用AVPlayer的子類AVQueuePlayer實現列表播放废登。在AVPlayer的基礎上,增加以下方法:

//通過給定的AVPlayerItem數組創(chuàng)建一個AVQueuePlayer實例
+ (instancetype)queuePlayerWithItems:(NSArray<AVPlayerItem *> *)items;
//通過給定的AVPlayerItem數組初始化一個AVQueuePlayer實例
- (AVQueuePlayer *)initWithItems:(NSArray<AVPlayerItem *> *)items;
//獲取當前播放隊列數組
- (NSArray<AVPlayerItem *> *)items;
//停止當前播放的诗轻,播放隊列中的下一首
- (void)advanceToNextItem;
//判斷是否可以插入AVPlayerItem
- (BOOL)canInsertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
//往播放隊列中插入新的AVPlayerItem
- (void)insertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
//移除指定的AVPlayerItem
- (void)removeItem:(AVPlayerItem *)item;
//移除所有播放隊列中的AVPlayerItem
- (void)removeAllItems;

*官方API中沒找到播放上一首的方法钳宪,所以其實直接用AVPlayer做列表播放也是可以的,自己維護一個播放列表數組扳炬,監(jiān)聽用戶點擊上一首和下一首按鈕吏颖,并監(jiān)聽播放結束事件,調用 AVPlayer 實例的replaceCurrentItemWithPlayerItem:方法傳入播放列表中的上一首或下一首就行恨樟。

后臺播放

首先在AppDelegate.m的- (BOOL)application:didFinishLaunchingWithOptions:方法中添加代碼:

 //設置后臺播放功能
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
[session setActive:YES error:nil];

然后在info.plist里面配置:

<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
</array>

鎖屏信息

1半醉、在播放控制界面接受遠程控制

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];
    // 開始接受遠程控制
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [self resignFirstResponder];  
}

- (void)viewWillDisappear:(BOOL)animated
{
// 接觸遠程控制
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
    [self becomeFirstResponder];
}
// 重寫父類成為響應者方法
- (BOOL)canBecomeFirstResponder
{
    return YES;
}

2、對遠程控制事件做出相應的操作

//重寫父類方法劝术,接受外部事件的處理
- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {
    NSLog(@"remote");
    if (receivedEvent.type == UIEventTypeRemoteControl) {
        
        switch (receivedEvent.subtype) { // 得到事件類型
                
            case UIEventSubtypeRemoteControlTogglePlayPause: // 暫停 ios6
                [self.player pause]; // 調用你所在項目的暫停按鈕的響應方法 下面的也是如此
                break;
                
            case UIEventSubtypeRemoteControlPreviousTrack:  // 上一首
                
                [self lastMusic:nil];
                break;
                
            case UIEventSubtypeRemoteControlNextTrack: // 下一首
                [self nextMusic:nil];
                break;
                
            case UIEventSubtypeRemoteControlPlay: //播放
                [self playMusic:nil];
                break;
                
            case UIEventSubtypeRemoteControlPause: // 暫停 ios7
                [self playMusic:nil];
                break;
                
            default:
                break;
        }
    }
}

3缩多、設置鎖屏主題

//鎖屏信息
    NSMutableDictionary *songInfo = [ [NSMutableDictionary alloc] init];
    //鎖屏圖片
    UIImage *img = [UIImage imageNamed:@"iPhoneX"];
    if (img) {
        MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc]initWithImage:img];
        [songInfo setObject: albumArt forKey:MPMediaItemPropertyArtwork ];
    }
    //鎖屏標題
    NSString *title = @"music";
    [songInfo setObject:[NSNumber numberWithFloat:100] forKey:MPMediaItemPropertyPlaybackDuration];
    [songInfo setObject:title forKey:MPMediaItemPropertyTitle];
    [songInfo setObject:title forKey:MPMediaItemPropertyAlbumTitle];
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo ];

通過耳機、鎖屏界面控制

// 直接使用sharedCommandCenter來獲取MPRemoteCommandCenter的shared實例
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

// 啟用播放命令 (鎖屏界面和上拉快捷功能菜單處的播放按鈕觸發(fā)的命令)
commandCenter.playCommand.enabled = YES;
// 為播放命令添加響應事件, 在點擊后觸發(fā)
[commandCenter.playCommand addTarget:self action:@selector(playAction:)];

// 播放, 暫停, 上下曲的命令默認都是啟用狀態(tài), 即enabled默認為YES
// 為暫停, 上一曲, 下一曲分別添加對應的響應事件
[commandCenter.pauseCommand addTarget:self action:@selector(pauseAction:)];
[commandCenter.previousTrackCommand addTarget:self action:@selector(previousTrackAction:)];
[commandCenter.nextTrackCommand addTarget:self action:@selector(nextTrackAction:)];

// 啟用耳機的播放/暫停命令 (耳機上的播放按鈕觸發(fā)的命令)
commandCenter.togglePlayPauseCommand.enabled = YES;
// 為耳機的按鈕操作添加相關的響應事件
[commandCenter.togglePlayPauseCommand addTarget:self action:@selector(playOrPauseAction:)];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末养晋,一起剝皮案震驚了整個濱河市衬吆,隨后出現的幾起案子,更是在濱河造成了極大的恐慌绳泉,老刑警劉巖逊抡,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異零酪,居然都是意外死亡冒嫡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門四苇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孝凌,“玉大人,你說我怎么就攤上這事月腋◇凹埽” “怎么了瓣赂?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辜窑。 經常有香客問我钩述,道長,這世上最難降的妖魔是什么穆碎? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任牙勘,我火速辦了婚禮,結果婚禮上所禀,老公的妹妹穿的比我還像新娘方面。我一直安慰自己,他們只是感情好色徘,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布恭金。 她就那樣靜靜地躺著,像睡著了一般褂策。 火紅的嫁衣襯著肌膚如雪横腿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天斤寂,我揣著相機與錄音耿焊,去河邊找鬼。 笑死遍搞,一個胖子當著我的面吹牛罗侯,可吹牛的內容都是我干的。 我是一名探鬼主播溪猿,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钩杰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诊县?” 一聲冷哼從身側響起讲弄,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎依痊,沒想到半個月后避除,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡抗悍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了钳枕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缴渊。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鱼炒,靈堂內的尸體忽然破棺而出衔沼,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布指蚁,位于F島的核電站菩佑,受9級特大地震影響,放射性物質發(fā)生泄漏凝化。R本人自食惡果不足惜稍坯,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搓劫。 院中可真熱鬧瞧哟,春花似錦、人聲如沸枪向。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秘蛔。三九已至陨亡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間深员,已是汗流浹背负蠕。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辨液,地道東北人虐急。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像滔迈,于是被迫代替她去往敵國和親止吁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容