iOS AVAudioSession 詳解

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è)置;

區(qū)別參照蘋果文檔

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)會自動配置AVAudioSessionCategoryOptionAllowBluetoothAVAudioSessionCategoryOptionDefaultToSpeaker
  • 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
  • AVAudioSessionCategoryOptionMixWithOthersAVAudioSessionCategoryPlayAndRecordAVAudioSessionCategoryMultiRoute默認不設(shè)置,若設(shè)置后,當程序同時啟動音頻輸入輸出時,允許程序后臺運行;AVAudioSessionCategoryPlayback默認不設(shè)置,若設(shè)置后,無論是鈴聲還是在靜音模式下,仍然能夠播放
  • AVAudioSessionCategoryOptionDuckOthers:當前session處于active時,其他音頻就是回避狀態(tài)(壓低聲音) AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryPlaybackAVAudioSessionCategoryMultiRoute 默認不混音,不回避
  • AVAudioSessionCategoryOptionAllowBluetooth:允許將藍牙作為可用途徑。支持AVAudioSessionCategoryPlayAndRecordAVAudioSessionCategoryRecord
  • 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];

參考文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容