iOS音訊-AVAudioSession
AVAudioSession就是用來管理多個APP對音訊硬體裝置(麥克風,揚聲器)的資源使用。
舉例一下AVAudioSession可以做這些事情
- 設定自己的APP是否和其他APP音訊同時存在,還是中斷其他APP聲音
- 在手機調到靜音模式下,自己的APP音訊是否可以播放出聲音
- 電話或者其他APP中斷自己APP的音訊的事件處理
- 指定音訊輸入和輸出的裝置(比如是聽筒輸出聲音,還是揚聲器輸出聲音)
- 是否支援錄音,錄音同時是否支援音訊播放
AVAudioSession Category
AVAudioSession的介面比較簡單。APP啟動的時候會自動啟用AVAudioSession,當然我們可以手動啟用程式碼如下。
//匯入標頭檔案
#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都對應是否支援下面四種能力
Interrupts non-mixable apps audio:是否打斷不支援混音播放的APP
Silenced by the Silent switch:是否會響應手機靜音鍵開關
Supports audio input:是否支援音訊錄製
-
Supports audio output:是否支援音訊播放
Category 是否允許音訊播放/錄音 是否打斷其他不支援混音APP 是否會被靜音鍵或鎖屏鍵靜音 AVAudioSessionCategoryAmbient 支援 否 是 AVAudioSessionCategoryAudioProcessing 不支援播放,不支援錄製 是 否 AVAudioSessionCategoryPlayback 只支援播放 預設YES,可以重寫為NO 否 AVAudioSessionCategoryRecord 只支援錄製 是 否(鎖屏下仍可錄製) AVAudioSessionCategorySoloAmbient 只支援播放 是 是 AVAudioSessionCategoryMultiRoute 支援播放,支援錄製 是 否 AVAudioSessionCategoryPlayAndRecord 支援播放,支援錄製 預設YES,可以重寫為NO 否
AVAudioSessionCategoryAmbient,只支援音訊播放。這個 Category,音訊會被靜音鍵和鎖屏鍵靜音。並且不會打斷其他應用的音訊播放。
AVAudioSessionCategorySoloAmbient,這個是系統預設使用的 Category,只支援音訊播放。音訊會被靜音鍵和鎖屏鍵靜音。和AVAudioSessionCategoryAmbient不同的是,這個會打斷其他應用的音訊播放
AVAudioSessionCategoryPlayback,只支援音訊播放。你的音訊不會被靜音鍵和鎖屏鍵靜音。適用於音訊是主要功能的APP,像網易雲這些音樂app,鎖屏後依然可以播放。
需要注意一下,選擇支援在靜音鍵切到靜音狀態以及鎖屏鍵切到鎖屏狀態下仍然可以播放音訊 Category 時,必須在應用中開啟支援後臺音訊功能,詳見 UIBackgroundModes。
- 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檢視錯誤原因
}
AVAudioSession Mode&&Options
剛剛介紹的Category定義了七種主場景,實際開發需求中有時候需要對Category進行微調整,我們發現這個介面還有兩個引數Mode和Options。
AVAudioSession Mode
我們通過讀取下面這條屬性獲取當前裝置支援的Mode
@property(readonly) NSArray<NSString *> *availableModes;
iOS下有七種mode來定製我們的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];
音訊中斷處理
中斷髮生時,應用程式的AVAudioSession會傳送通知AVAudioSessionInterruptionNotification,註冊通知程式碼如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
在接收到通知的userInfo中,會包含一個AVAudioSessionInterruptionTypeKey,用來標識中斷開始和中斷結束.
當中斷型別為AVAudioSessionInterruptionTypeKeyEnded時,userInfo中還會包含一個AVAudioSessionInterruptionOptions來表明音訊會話是否已經重新啟用以及是否可以再次播放.示例程式碼如下:
- (void)handleInterruption:(NSNotification *)notification
{
_descriptionLabel.text = @"handleInterruption";
NSDictionary *info = notification.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan) {
//Handle InterruptionBegan
}else{
AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
if (options == AVAudioSessionInterruptionOptionShouldResume) {
//Handle Resume
}
}
}
在iOS裝置上新增或移除音訊輸入,輸出線路時,會發生線路改變,比如使用者插入耳機或斷開USB麥克風.當這些事件發生時,音訊會根據情況改變輸入或輸入線路,同時AVAudioSession會傳送一個相關變化的通知AVAudioSessionRouteChangeNotification.註冊通知的相關程式碼如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
根據蘋果公司的文件,當使用者插入耳機時,隱含的意思是使用者不希望外界聽到具體的音訊了內容,這就意味著當使用者斷開耳機時,播放的內容可能需要保密,所以我們需要在斷開耳機時停止音訊播放.
AVAudioSessionRouteChangeNotification通知的userinfo中會帶有通知傳送的原因資訊及前一個線路的描述.線路變更的原因儲存在userinfo的AVAudioSessionRouteChangeReasonKey值中,通過返回值可以推斷出不同的事件,對於舊音訊裝置中斷對應的reason為AVAudioSessionRouteChangeReasonOldDeviceUnavailable.但光憑這個reason並不能斷定是耳機斷開,所以還需要使用通過AVAudioSessionRouteChangePreviousRouteKey獲得上一線路的描述資訊,注意線路的描述資訊整合在一個輸入NSArray和一個輸出NSArray中,陣列中的元素都是AVAudioSessionPortDescription物件.我們需要從線路描述中找到第一個輸出介面並判斷其是否為耳機介面,如果為耳機,則停止播放.
- (void)handleRouteChange:(NSNotification *)notification
{
NSDictionary *info = notification.userInfo;
AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { //舊音訊裝置斷開
//獲取上一線路描述資訊
AVAudioSessionRouteDescription *previousRoute = info[AVAudioSessionRouteChangePreviousRouteKey];
//獲取上一線路的輸出裝置型別
AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
NSString *portType = previousOutput.portType;
if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
}
}
}
總結:AVAudioSession的作用就是管理音訊這一唯一硬體資源的分配,通過調優合適的AVAudioSession來適配我們的APP對於音訊的功能需求。切換音訊場景時候,需要相應的切換AVAudioSession。
相關文章
- iOS-音訊-AVAudioSessioniOS音訊Session
- iOS AVAudioPlayer(音訊播放)iOS音訊
- iOS 音訊-audioUnit 總結iOS音訊
- IOS音視訊(二)AVFoundation視訊捕捉iOS
- iOS開發系列--音訊播放、錄音、視訊播放、拍照、視訊錄製(轉)iOS音訊
- iOS實現音訊進度條效果iOS音訊
- 我的 iOS 音訊處理總結iOS音訊
- iOS下WebRTC音視訊通話(一)iOSWeb
- iOS音訊程式設計之實時語音通訊(對講機功能)iOS音訊程式設計
- iOS ARKit錄製視訊(AVAssetWriter & 有聲音)iOS
- IOS音視訊(四十三)AVFoundation 之 Audio SessioniOSSession
- iOS 實時音訊採集與播放Audio Unit使用iOS音訊
- iOS: Audio File 音訊檔案錄製(支援VBR,CBR)iOS音訊
- Audio Unit: iOS中最底層最強大音訊控制APIiOS音訊API
- iOS採集錄製音視訊API選擇推薦iOSAPI
- Audio Hijack教程:如何捕獲iOS裝置中的音訊iOS音訊
- 音視訊--音訊入門音訊
- 音視訊–音訊入門音訊
- 騰訊音樂招 iOS 開發, base 深圳,要求:本科、三年、OC,懂音視訊開發優先。iOS
- 轉載:iOS音視訊實時採集硬體編碼iOS
- More-iOS開發中的音訊相關內容總結iOS音訊
- iOS---語音轉文字iOS
- 短視訊“音訊化”,音樂“視訊化”音訊
- 友好訪問許可權篇:訪問語音、相簿、通訊錄----iOS訪問許可權iOS
- android音視訊指南-管理音訊焦點Android音訊
- Mac 使用音訊工具分析音訊資料Mac音訊
- 音訊訊號表徵音訊
- HTML 音訊HTML音訊
- Android 音視訊 - MediaCodec 編解碼音視訊Android
- 一步一步教你實現iOS音訊頻譜動畫(二)iOS音訊動畫
- 一步一步教你實現iOS音訊頻譜動畫(一)iOS音訊動畫
- 小程式自定義音訊元件,帶滾動條,IOS迴圈失效問題音訊元件iOS
- iOS錄音模組實踐[AVAudioRecoder]iOS
- Android 音視訊開發 視訊編碼,音訊編碼格式Android音訊
- 多款抖音獨代手遊稱霸iOS下載榜,騰訊該慌麼?iOS
- ffmpeg 去除音訊中的靜音音訊
- 音訊處理音訊
- SoundSource音訊控制音訊