
AVAudioSession
簡要說說AVAudioSession,AVAudioSession是蘋果用來管理App對音頻硬件(I / O)的資源使用;比如說:
- 設(shè)置APP與其他APP是否混音,或者中斷、降低其他App聲音
- 手機靜音下,APP是否可以播放聲音
- 指定音頻輸入或者輸出設(shè)備
- 是否支持APP錄制,是否可以邊錄制邊播放
- 聲音中斷的優(yōu)先級(電話接入中斷APP音頻處理)
在APP的運行過程中,AudioSession的配置影響所有的音頻活動。你可以查詢Audio Session來發(fā)現(xiàn)設(shè)備的硬件特性。如聲道數(shù)(channel count)、采樣率(sample rate)、和音頻輸入的可用性(availability of audio unit)
AVAudioSession 激活
/* 設(shè)置為激活或者失活。激活音頻會話是一個同步(阻塞)操作 */
- (BOOL)setActive:(BOOL)active
error:(NSError * _Nullable *)outError;
/* 調(diào)用該方法 通知中斷的應用程序中斷已經(jīng)結(jié)束,它可以恢復播放,僅在會話停用時有效
active:NO
options:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation */
- (BOOL)setActive:(BOOL)active withOptions:(AVAudioSessionSetActiveOptions)options error:(NSError **)outError;
AVAudioSession 硬件設(shè)置
/* 首選硬件采樣率 */
- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError
/* 首選的硬件IO緩沖區(qū)持續(xù)時間(以秒為單位) */
- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError **)outError
// 輸入通道數(shù)
- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count error:(NSError **)outError
// 輸出通道數(shù)
- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count error:(NSError **)outError
// 設(shè)置立體聲方向
- (BOOL)setPreferredInputOrientation:(AVAudioStereoOrientation)orientation error:(NSError **)outError
// 使用此方法可臨時覆蓋內(nèi)置揚聲器的輸出
- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride error:(NSError **)outError
設(shè)置音頻輸出方式
當iPhone接入多個外部設(shè)備時,AudioSeesion將遵循last-in wins原則(后入為主),即聲音將被導向到最后接入的設(shè)備。在沒有接入任何設(shè)備時,一般情況下聲音會默認從揚聲器發(fā)出,但有一個例外:在使用AVAudioSessionCategoryPlayAndRecord這種category下,聽筒成為默認的輸出設(shè)備。
如果需要改變揚聲器的輸出,有以下幾種方式:
- 方式一:調(diào)用音頻輸出方法
overrideOutputAudioPort:(這種方式調(diào)用更短暫)
如果選擇揚聲器輸出,設(shè)置為AVAudioSessionPortOverrideSpeaker;
如果默認狀態(tài)輸出,設(shè)置為AVAudioSessionPortOverrideNone; - 方式二:設(shè)置
AVAudioSessionCategoryOption值
如果選擇揚聲器輸出,設(shè)置為AVAudioSessionCategoryOptionDefaultToSpeaker;
如果默認狀態(tài)輸出,不設(shè)置;
AVAudioSessionCategory
在AVAudioSession中可以設(shè)置Category和Option,每一種Category都對應是否支持以下幾種能力:
- Interrupts non-mixable apps audio :是否打斷不支持混音播放的APP
- Silenced by the Silent switch:是否會被手機靜音鍵開關(guān)影響
- Supports audio input / output:是否支持音頻錄制、播放
| Category | Play | Record | MixWithOther | Silenced |
|---|---|---|---|---|
| AVAudioSessionCategoryAmbient | ? | ? | ? | ? |
| AVAudioSessionCategorySoloAmbient | ? | ? | ? | ? |
| AVAudioSessionCategoryPlayback | ? | ? | 可選,默認? | ? |
| AVAudioSessionCategoryRecord | ? | ? | ? | ? |
| AVAudioSessionCategoryPlayAndRecord | ? | ? | 可選,默認? | ? |
| AVAudioSessionCategoryAudioProcessing | ? | ? | ? | ? |
| AVAudioSessionCategoryMultiRoute | ? | ? | ? | ? |
-
AVAudioSessionCategoryAmbient:只支持音頻播放,音頻播放時會被靜音鍵和鎖屏鍵靜音,可以與其他APP混音。 -
AVAudioSessionCategorySoloAmbient: 系統(tǒng)默認,只支持音頻播放,音頻會被靜音鍵和鎖屏鍵靜音,會打斷其他APP音頻播放。 -
AVAudioSessionCategoryPlayback:支持音頻播放,音頻不會被靜音鍵和鎖屏鍵靜音,適用于音頻是主要功能的APP,鎖屏后依然可以播放。(后臺播放需要開啟音頻相關(guān)的后臺支持UIBackgroundModes) -
AVAudioSessionCategoryRecord: 只支持音頻錄制,不支持播放。 -
AVAudioSessionCategoryPlayAndRecord: 支持音頻錄制和播放,聲音在沒有外設(shè)的情況下,默認為聽筒播放。 -
AVAudioSessionCategoryAudioProcessing: 使用硬件編解碼器或信號處理器而不播放或錄制音頻時使用此類別。 -
AVAudioSessionCategoryMultiRoute: 使用硬件編解碼器或信號處理器而不播放或錄制音頻時使用此類別。
/* set session category */
- (BOOL)setCategory:(AVAudioSessionCategory)category error:(NSError **)outError API_AVAILABLE(ios(3.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
/* set session category with options */
- (BOOL)setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
/* set session category and mode with options */
- (BOOL)setCategory:(AVAudioSessionCategory)category mode:(AVAudioSessionMode)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0)) API_UNAVAILABLE(macos);
/* set session category, mode, routing sharing policy, and options */
- (BOOL)setCategory:(AVAudioSessionCategory)category mode:(AVAudioSessionMode)mode routeSharingPolicy:(AVAudioSessionRouteSharingPolicy)policy options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(11.0), tvos(11.0), watchos(5.0)) API_UNAVAILABLE(macos);
注意:設(shè)置category要考慮設(shè)置失敗的情況
AVAudioSessionMode
| AVAudioSessionMode | Category | Scene |
|---|---|---|
| AVAudioSessionModeDefault | All | 默認 |
| AVAudioSessionModeVoiceChat | AVAudioSessionCategoryPlayAndRecord | VoIP (語音通話) |
| AVAudioSessionModeGameChat | AVAudioSessionCategoryPlayAndRecord | 游戲模式 |
| AVAudioSessionModeVideoRecording | AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord | 適用于使用攝像頭采集視頻的應用 |
| AVAudioSessionModeMeasurement | AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord | 最小化系統(tǒng) |
| AVAudioSessionModeMoviePlayback | AVAudioSessionCategoryPlayback | 視頻播放 |
| AVAudioSessionModeVideoChat | AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord | 視頻通話 |
| AVAudioSessionModeSpokenAudio | AVAudioSessionCategorySoloAmbient、AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryMultiRoute | 有聲讀物 |
| AVAudioSessionModeVoicePrompt | - | 語音提示 |
-
AVAudioSessionModeDefault:默認模式 兼容所有category -
AVAudioSessionModeVoiceChat:適用于語音聊天VoIP -
AVAudioSessionModeGameChat:適用于游戲模式,不需要主動設(shè)置(若不想用GKVoiceChat但希望達到類似功能,可以使用AVAudioSessionModeVoiceChat) -
AVAudioSessionModeVideoRecording:適用于使用攝像頭采集視頻的應用 -
AVAudioSessionModeMeasurement:適用于希望將系統(tǒng)提供的用于輸入和/或輸出音頻信號的信號處理的影響最小化的應用 -
AVAudioSessionModeMoviePlayback:適用于AVAudioSessionCategoryPlayback下的視頻播放 -
AVAudioSessionModeVideoChat:適用于視頻聊天 系統(tǒng)會自動配置AVAudioSessionCategoryOptionAllowBluetooth和AVAudioSessionCategoryOptionDefaultToSpeaker -
AVAudioSessionModeSpokenAudio:當其他應用程序播放短暫的語音提示時,希望自己的音頻暫停而不是回避(聲音變?。r使用 -
AVAudioSessionModeVoicePrompt:當程序內(nèi)音頻為簡單的語音提示時使用。適用于導航中的播報
AVAudioSessionCategoryOptions
| AVAudioSessionCategoryOption | Function Describe | Supports Category |
|---|---|---|
| AVAudioSessionCategoryOptionMixWithOthers | 支持混音 |
AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
|
| AVAudioSessionCategoryOptionDuckOthers | 降低其他應用的音量 |
AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
|
| AVAudioSessionCategoryOptionAllowBluetooth | 支持藍牙音頻輸入 |
AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
|
| AVAudioSessionCategoryOptionDefaultToSpeaker | 設(shè)置默認輸出到揚聲器 | AVAudioSessionCategoryPlayAndRecord |
| AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers | 音頻播放過程中,支持中斷其他應用 |
AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
|
| AVAudioSessionCategoryOptionAllowBluetoothA2DP | 支持立體聲藍牙 |
AVAudioSessionCategoryAmbient AVAudioSessionCategorySoloAmbient AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord
|
| AVAudioSessionCategoryOptionAllowAirPlay | 支持遠程AirPlay | AVAudioSessionCategoryPlayAndRecord |
-
AVAudioSessionCategoryOptionMixWithOthers:AVAudioSessionCategoryPlayAndRecord 、AVAudioSessionCategoryMultiRoute默認不設(shè)置,若設(shè)置后,當程序同時啟動音頻輸入輸出時,允許程序后臺運行;AVAudioSessionCategoryPlayback默認不設(shè)置,若設(shè)置后,無論是鈴聲還是在靜音模式下,仍然能夠播放 -
AVAudioSessionCategoryOptionDuckOthers:當前session處于active時,其他音頻就是回避狀態(tài)(壓低聲音) AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryPlayback、AVAudioSessionCategoryMultiRoute 默認不混音,不回避 -
AVAudioSessionCategoryOptionAllowBluetooth:允許將藍牙作為可用途徑。支持AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord -
AVAudioSessionCategoryOptionDefaultToSpeaker:允許改變音頻session默認選擇內(nèi)置揚聲器(免提);僅支持AVAudioSessionCategoryPlayAndRecord -
AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers:如果設(shè)置了這個選項,系統(tǒng)就會將你的音頻與其他音頻會話混合,但是會中斷(并停止)使用AVAudioSessionModeSpokenAudio模式的音頻會話;只要會話處于活動狀態(tài),它就會暫停來自其他應用程序的音頻。音頻會話失活后,系統(tǒng)恢復被中斷的應用程序的音頻。 -
AVAudioSessionCategoryOptionAllowBluetoothA2DP:A2DP是一種立體聲、僅輸出的配置文件用于更高帶寬的音頻。如果使用AVAudioSessionCategoryAmbient、AVAudioSessionCategorySoloAmbient或AVAudioSessionCategoryPlayback類別,系統(tǒng)會自動路由到A2DP端口;從iOS 10.0開始,使用AVAudioSessionCategoryPlayAndRecord類別的應用程序也可以將輸出路由到配對的藍牙A2DP設(shè)備。要啟用此行為,請在設(shè)置音頻會話的類別時傳遞此類別選項。 -
AVAudioSessionCategoryOptionAllowAirPlay:設(shè)置此選項可使音頻會話將音頻輸出路由到AirPlay設(shè)備。設(shè)置為AVAudioSessionCategoryPlayAndRecord,則只能顯式地設(shè)置此選項。對于大多數(shù)其他音頻會話類別,系統(tǒng)隱式地設(shè)置此選項。
注意: 如果應用中使用到MPNowPlayingInfoCenter,最好避免設(shè)置AVAudioSessionCategoryOptionMixWithOthers;因為一旦設(shè)置了這個值之后,那么MPNowPlayingInfoCenter就不能正常顯示信息
AVAudioSessionRouteSharingPolicy
路由策略:
- AVAudioSessionRouteSharingPolicyDefault 遵循正常的規(guī)則路由音頻輸出
- AVAudioSessionRouteSharingPolicyLongFormAudio 將輸出路由到共享的長格式音頻輸出
-
AVAudioSessionRouteSharingPolicyLongForm已廢棄 - AVAudioSessionRouteSharingPolicyIndependent 應用程序不應試圖直接設(shè)置此值。在iOS上,當路由選擇器UI用于將視頻定向到無線路由時,系統(tǒng)將設(shè)置此值。
- AVAudioSessionRouteSharingPolicyLongFormVideo 將輸出路由到共享的長格式視頻輸出(使用此策略的應用程序在其Info.plist中設(shè)置AVInitialRouteSharingPolicy鍵)
AVAudioSessionNotification
AVAudioSession有以下多個通知來提示用戶事件;
- AVAudioSessionInterruptionNotification:系統(tǒng)中斷響應通知
- AVAudioSessionInterruptionNotification:音頻線路變更通知
- AVAudioSessionSilenceSecondaryAudioHintNotification:其他應用音頻狀態(tài)提示通知
AVAudioSessionInterruptionNotification
當App內(nèi)音頻被中斷,系統(tǒng)會將AudioSession置為失活狀態(tài),音頻也會因此立即停止。當一個別的App的AudioSession被激活并且它的類別未設(shè)置與系統(tǒng)類別或你應用程序類別混合時,中斷就會發(fā)生。你的應用程序在收到中斷通知后應該保存當時的狀態(tài),以及更新用戶界面等相關(guān)操作。通過注冊AVAudioSessionInterruptionNotification通知,可以處理中斷的開始和結(jié)束。
/* keys for AVAudioSessionInterruptionNotification */
/* Value is an NSNumber representing an AVAudioSessionInterruptionType */
AVAudioSessionInterruptionTypeKey
typedef NS_ENUM(NSUInteger, AVAudioSessionInterruptionType)
{
AVAudioSessionInterruptionTypeBegan = 1, /* the system has interrupted your audio session */
AVAudioSessionInterruptionTypeEnded = 0, /* the interruption has ended */
};
/* Only present for end interruption events. Value is of type AVAudioSessionInterruptionOptions.*/
AVAudioSessionInterruptionOptionKey
typedef NS_OPTIONS(NSUInteger, AVAudioSessionInterruptionOptions)
{
AVAudioSessionInterruptionOptionShouldResume = 1
};
提示:這里的通知的中斷開始和中斷結(jié)束不一定都會出現(xiàn)(蘋果文檔中有提到)
AVAudioSessionRouteChangeNotification
當用戶連接或者斷開音頻輸入,輸出設(shè)備時(插拔耳機、或者藍牙耳機的斷開、連接),音頻線路發(fā)生變更,通過注冊AVAudioSessionRouteChangeNotification通知,可以在音頻線路發(fā)生變更時做出相應處理。
/* keys for AVAudioSessionRouteChangeNotification */
/* value is an NSNumber representing an AVAudioSessionRouteChangeReason */
AVAudioSessionRouteChangeReasonKey
typedef NS_ENUM(NSUInteger, AVAudioSessionRouteChangeReason)
{
AVAudioSessionRouteChangeReasonUnknown = 0,
AVAudioSessionRouteChangeReasonNewDeviceAvailable = 1, //設(shè)備可用(耳機插好)
AVAudioSessionRouteChangeReasonOldDeviceUnavailable = 2, //設(shè)備不可用(耳機被拔下)
AVAudioSessionRouteChangeReasonCategoryChange = 3, // 設(shè)置的分類被改變
AVAudioSessionRouteChangeReasonOverride = 4, // 路由被覆蓋
AVAudioSessionRouteChangeReasonWakeFromSleep = 6, // 設(shè)備被激活
AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory = 7, //當前類別沒有路由時返回
AVAudioSessionRouteChangeReasonRouteConfigurationChange = 8 // added in iOS 7
};
AVAudioSessionSilenceSecondaryAudioHintNotification
當來自其他應用的主音頻啟動,或者停止時,通過注冊AVAudioSessionSilenceSecondaryAudioHintNotification通知,前臺應用可以作為啟動或者禁用次要音頻的提示;
/* keys for AVAudioSessionSilenceSecondaryAudioHintNotification */
/* value is an NSNumber representing an AVAudioSessionSilenceSecondaryAudioHintType */
AVAudioSessionSilenceSecondaryAudioHintTypeKey
typedef NS_ENUM(NSUInteger, AVAudioSessionSilenceSecondaryAudioHintType)
{
AVAudioSessionSilenceSecondaryAudioHintTypeBegin = 1, /* the system is indicating that another application's primary audio has started */
AVAudioSessionSilenceSecondaryAudioHintTypeEnd = 0, /* the system is indicating that another application's primary audio has stopped */
};
AVAudioSession 常用音頻建議
使用AVAudioSessionCategoryRecord,AVAudioSessionCategoryPlayAndRecord,AVAudioSessionCategoryPlayback類別的APP,蘋果建議的準則如下:
- 當應用程序進入前臺時,請等待用戶按下“播放”或“錄制”按鈕,然后再激活音頻會話。
- 當應用程序處于前臺時,除非中斷,否則請保持音頻會話處于活動狀態(tài)。
- 如果應用程序在過渡到后臺時沒有活躍的播放或錄制音頻,請停用其音頻會話。這樣可以防止其音頻會話被另一個不可混合的應用程序中斷,或者在應用程序被系統(tǒng)掛起時響應中斷其音頻會話。
- 在被中斷后更新用戶界面的播放或錄制到暫停。請勿停用音頻會話。
- 觀察
AVAudioSessionInterruptionNotification有關(guān)音頻會話中斷的通知類型。中斷結(jié)束后,請勿再次開始播放或錄制音頻,除非該應用在中斷之前就已經(jīng)開始了。 - 如果路由更改是由拔出事件引起的,則暫停播放或錄制,但請保持音頻會話處于活動狀態(tài)。
- 假設(shè)應用程序的音頻會話從掛起狀態(tài)轉(zhuǎn)換為前臺狀態(tài)時處于失活狀態(tài)。當用戶按下“播放”或“錄制”按鈕時,重新激活音頻會話。
- 確保
UIBackgroundModes已設(shè)置音頻標志。 - 注冊遠程控制事件(請參閱參考資料
MPRemoteCommandCenter),并為您的媒體提供適當?shù)摹罢诓シ拧毙畔ⅲㄕ垍㈤唴⒖假Y料MPNowPlayingInfoCenter)。 - 使用一個
MPVolumeView對象顯示系統(tǒng)音量滑塊和路線選擇器。 - 使用后臺任務而不是靜默播放流,以防止應用程序被暫停。
- 要求用戶許可使用該
requestRecordPermission:方法記錄輸入。不要依靠操作系統(tǒng)來提示用戶。 - 對于錄制應用程序,請使用
AVAudioSessionCategoryPlayAndRecord類別而不是AVAudioSessionCategoryRecord類別?!皟H記錄”類別幾乎使所有系統(tǒng)輸出靜音,并且通常對于大多數(shù)應用程序而言過于嚴格。
詳情可以參照蘋果指南
AVAudioSession 聲音常用處理
- 播放應用內(nèi)的音頻時暫停外部音樂
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:0 error:&error];
[[AudioSession sharedInstance] setActive:YES error:&error];
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
- 混音播放外部音頻,同時插播一條應用內(nèi)的語音(播放語音時,外部音頻降低音量,播放語音完畢后,外部音頻恢復音量)
/* start */
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDuckOthers error:&error];
/* end */
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
- 喚起其他App播放
[[AudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
參考文檔