iOS-音頻-AVAudioSession

1. AVAudioSession 概述

最近一年一直在作IPC Camera的iOS客戶端開發。和音頻打交道,必需要弄清楚 AVAudioSession。 先看下蘋果的官方圖: html

Audio Session

能夠看到AVAudioSession就是用來管理多個APP對音頻硬件設備(麥克風,揚聲器)的資源使用。ios

舉例一下AVAudioSession能夠作這些事情bash

  • 設置本身的APP是否和其餘APP音頻同時存在,仍是中斷其餘APP聲音
  • 在手機調到靜音模式下,本身的APP音頻是否能夠播放出聲音
  • 電話或者其餘APP中斷本身APP的音頻的事件處理
  • 指定音頻輸入和輸出的設備(好比是聽筒輸出聲音,仍是揚聲器輸出聲音)
  • 是否支持錄音,錄音同時是否支持音頻播放

2. AVAudioSession Category

AVAudioSession的接口比較簡單。APP啓動的時候會自動幫激活AVAudioSession,固然咱們能夠手動激活代碼以下。session

//導入頭文件
    #import <AVFoundation/AVFoundation.h>

    //AVAudioSession是一個單例類
    AVAudioSession *session = [AVAudioSession sharedInstance];
    //AVAudioSessionCategorySoloAmbient是系統默認的category
    [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    //激活AVAudioSession
    [session setActive:YES error:nil];
複製代碼

能夠看到設置session這裏有兩個參數,category和options Category iOS下目前有七種,每種Category都對應是否支持下面四種能力app

  • Interrupts non-mixable apps audio:是否打斷不支持混音播放的APP
  • Silenced by the Silent switch:是否會響應手機靜音鍵開關
  • Supports audio input:是否支持音頻錄製
  • Supports audio output:是否支持音頻播放

下面用圖表來直觀的看下每種category具體的能力集ide

Category 是否容許音頻播放/錄音 是否打斷其餘不支持混音APP 是否會被靜音鍵或鎖屏鍵靜音
AVAudioSessionCategoryAmbient 只支持播放
AVAudioSessionCategoryAudioProcessing 不支持播放,不支持錄製
AVAudioSessionCategoryMultiRoute 支持播放,支持錄製
AVAudioSessionCategoryPlayAndRecord 支持播放,支持錄製 默認YES,能夠重寫爲NO
AVAudioSessionCategoryPlayback 只支持播放 默認YES,能夠重寫爲NO
AVAudioSessionCategoryRecord 只支持錄製 否(鎖屏下仍可錄製)
AVAudioSessionCategorySoloAmbient 只支持播放
  • AVAudioSessionCategoryAmbient,只支持音頻播放。這個 Category,音頻會被靜音鍵和鎖屏鍵靜音。而且不會打斷其餘應用的音頻播放。ui

  • AVAudioSessionCategorySoloAmbient,這個是系統默認使用的 Category,只支持音頻播放。音頻會被靜音鍵和鎖屏鍵靜音。和AVAudioSessionCategoryAmbient不一樣的是,這個會打斷其餘應用的音頻播放spa

  • AVAudioSessionCategoryPlayback,只支持音頻播放。你的音頻不會被靜音鍵和鎖屏鍵靜音。適用於音頻是主要功能的APP,像網易雲這些音樂app,鎖屏後依然能夠播放。code

須要注意一下,選擇支持在靜音鍵切到靜音狀態以及鎖屏鍵切到鎖屏狀態下仍然能夠播放音頻 Category 時,必須在應用中開啓支持後臺音頻功能,詳見 UIBackgroundModescdn

  • AVAudioSessionCategoryRecord,只支持音頻錄製。不支持播放。
  • AVAudioSessionCategoryPlayAndRecord,支持音頻播放和錄製。音頻的輸入和輸出不須要同步進行,也能夠同步進行。須要音頻通話類應用,可使用這個 Category。
  • AVAudioSessionCategoryAudioProcessing,只支持本地音頻編解碼處理。不支持播放和錄製。
  • AVAudioSessionCategoryMultiRoute,支持音頻播放和錄製。容許多條音頻流的同步輸入和輸出。(好比USB鏈接外部揚聲器輸出音頻,藍牙耳機同時播放另外一路音頻這種特殊需求)

咱們也能夠經過AVAudioSession的屬性來讀取當前設備支持的Category

@property(readonly) NSArray<NSString *> *availableCategories;
複製代碼

這樣能夠保證設備兼容性。

設置Category的代碼示例以下

NSError *setCategoryError = nil;
BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
if (!success) { 
    //這裏能夠讀取setCategoryError.localizedDescription查看錯誤緣由
}
複製代碼

3. AVAudioSession Mode&&Options

剛剛介紹的Category定義了七種主場景,實際開發需求中有時候須要對Category進行微調整,咱們發現這個接口還有兩個參數Mode和Options。

/* set session category and mode with options */
- (BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
複製代碼

AVAudioSession Mode

咱們經過讀取下面這條屬性獲取當前設備支持的Mode

@property(readonly) NSArray<NSString *> *availableModes;
複製代碼

iOS下有七種mode來定製咱們的Category行爲

模式 兼容的 Category 場景
AVAudioSessionModeDefault All 默認模式
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 遊戲錄製,GKVoiceChat自動設置
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 錄製視頻
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 視頻播放
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小系統
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 視頻通話

下面逐一介紹下每一個Mode

  • AVAudioSessionModeDefault,默認模式,與全部的 Category 兼容

  • AVAudioSessionModeVoiceChat,適用於VoIP 類型的應用。只能是 AVAudioSessionCategoryPlayAndRecord Category下。在這個模式系統會自動配置AVAudioSessionCategoryOptionAllowBluetooth 這個選項。系統會自動選擇最佳的內置麥克風組合支持語音聊天。

  • AVAudioSessionModeVideoChat,用於視頻聊天類型應用,只能是 AVAudioSessionCategoryPlayAndRecord Category下。適在這個模式系統會自動配置 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 選項。系統會自動選擇最佳的內置麥克風組合支持視頻聊天。

  • AVAudioSessionModeGameChat,適用於遊戲類應用。使用 GKVoiceChat 對象的應用會自動設置這個模式和 AVAudioSessionCategoryPlayAndRecord Category。實際參數和AVAudioSessionModeVideoChat一致

  • AVAudioSessionModeVideoRecording,適用於使用攝像頭採集視頻的應用。只能是 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord 這兩個 Category下。這個模式搭配 AVCaptureSession API 結合來用能夠更好地控制音視頻的輸入輸出路徑。(例如,設置 automaticallyConfiguresApplicationAudioSession 屬性,系統會自動選擇最佳輸出路徑。

  • AVAudioSessionModeMeasurement,最小化系統。只用於 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayback 這幾種 Category。

  • AVAudioSessionModeMoviePlayback,適用於播放視頻的應用。只用於 AVAudioSessionCategoryPlayback 這個Category。

AVAudioSession Options

咱們還可使用options去微調Category行爲,以下表

Option Option功能說明 兼容的 Category
AVAudioSessionCategoryOptionMixWithOthers 支持和其餘APP音頻 mix AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers 系統智能調低其餘APP音頻音量 AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetooth 支持藍牙音頻輸入 AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker 設置默認輸出音頻到揚聲器 AVAudioSessionCategoryPlayAndRecord

調優咱們的Category

經過Category和合適的Mode和Options的搭配咱們能夠調優出咱們的效果,下面舉兩個應用場景:

用太高德地圖的都知道,在後臺播放QQ音樂的時候,若是導航語音出來,QQ音樂不會中止,而是被智能壓低和混音,等導航語音播報完後,QQ音樂正常播放,這裏咱們須要後臺播放音樂,因此Category使用AVAudioSessionCategoryPlayback,須要混音和智能壓低其餘APP音量,因此Options選用 AVAudioSessionCategoryOptionMixWithOthers和AVAudioSessionCategoryOptionDuckOthers

代碼示例以下

BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
複製代碼

又或者我但願AVAudioSessionCategoryPlayAndRecord這個Category默認的音頻由揚聲器播放,那麼能夠調用這個接口去調整Category

- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
複製代碼

經過選擇合適和Category,mode和options,就能夠調優音頻的輸入輸出,來知足平常開發需求(須要注意的是Category,mode,option是搭配使用的,而不是簡單組合,也就是說某種Category支持某些mode和option,從上面的表中也能夠看出這一點)

4. 音頻中斷處理

其餘APP或者電話會中斷咱們的APP音頻,因此相應的咱們要作出處理。 咱們能夠經過監聽AVAudioSessionInterruptionNotification這個key獲取音頻中斷事件

回調回來Userinfo有鍵值

  • AVAudioSessionInterruptionTypeKey: 取值AVAudioSessionInterruptionTypeBegan表示中斷開始 取值AVAudioSessionInterruptionTypeEnded表示中斷結束

中斷開始:咱們須要作的是保存好播放狀態,上下文,更新用戶界面等 中斷結束:咱們要作的是恢復好狀態和上下文,更新用戶界面,根據需求準備好以後選擇是否激活咱們session。

選擇不一樣的音頻播放技術,處理中斷方式也有差異,具體以下:

  • System Sound Services:使用 System Sound Services 播發音頻,系統會自動處理,不受APP控制,當中斷髮生時,音頻播放會靜音,當中斷結束後,音頻播放會恢復。

  • AV Foundation framework:AVAudioPlayer 類和 AVAudioRecorder 類提供了中斷開始和結束的 Delegate 回調方法來處理中斷。中斷髮生,系統會自動中止播放,須要作的是記錄播放時間等狀態,更新用戶界面,等中斷結束後,再次調用播放方法,系統會自動激活session。

  • Audio Queue Services, I/O audio unit:使用aduio unit這些技術須要處理中斷,須要作的是記錄播放或者錄製的位置,中斷結束後本身恢復audio session。

  • OpenAL:使用 OpenAL 播放時,一樣須要本身監聽中斷。管理 OpenAL上下文,用戶中斷結束後恢復audio session。

須要注意的是:1. 有中斷開始事件,不必定對應有中斷結束事件,因此須要在用戶進入前臺,點擊UI操做的時候,須要保存好播放狀態和對Audio Session管理,以便不影響APP的音頻功能。2.音頻資源競爭上,必定是電話優先。3. AVAudioSession一樣能夠監聽外設音頻狀態,好比耳機拔入拔出。這裏不作累述

5. AVAudioSession總結

AVAudioSession的做用就是管理音頻這一惟一硬件資源的分配,經過調優合適的AVAudioSession來適配咱們的APP對於音頻的功能需求。切換音頻場景時候,須要相應的切換AVAudioSession。

參考文獻:Audio Session Programming Guide

相關文章
相關標籤/搜索