本文轉自:[AVAudioSession(3):定製 Audio Session 的 Category | www.samirchen.com][2] 本文內容主要來源於 [Working with Categories][3]。 對於 Audio Session 來說,與之對應的 Category ...
本文轉自:AVAudioSession(3):定製 Audio Session 的 Category | www.samirchen.com
本文內容主要來源於 Working with Categories。
對於 Audio Session 來說,與之對應的 Category 是闡釋其音頻行為的關鍵信息。比如:你的 App 的聲音是否應該受到手機的靜音鍵的控制、你的 App 使不使用音頻輸入或輸出、其他音樂能否和你的 Audio 共存播放等等。
每一種 Category 都指定了是否支持下列這些能力:
Interrupts non-mixable apps audio
:是否打斷不支持混音播放的應用。如果是,則當你的應用的音頻開始播放時,則那些不支持混音播放的應用的音頻會被打斷。Silenced by the Silent switch
:是否響應手機靜音鍵。如果是,則當手機靜音鍵被撥至靜音狀態時,你的音頻會被靜音。Supports audio input
:是否支持音頻輸入。如果是,你的應用就可以錄音。Supports audio output
:是否支持音頻輸出。如果是,你的應用就可以播放音頻。
下麵是各種 Category 的能力表格:
Category | 是否會被靜音鍵或鎖屏鍵靜音 | 是否打斷不支持混音播放的應用 | 是否允許音頻輸入/輸出 |
---|---|---|---|
AVAudioSessionCategoryAmbient | Yes | NO | 只輸出 |
AVAudioSessionCategoryAudioProcessing | - | YES | 無輸入和輸出 |
AVAudioSessionCategoryMultiRoute | NO | YES | 支持輸入和輸出 |
AVAudioSessionCategoryPlayAndRecord | NO | 預設 YES,可重寫開關置為 NO | 支持輸入和輸出 |
AVAudioSessionCategoryPlayback | NO | 預設 YES,可重寫開關置為 NO | 只輸出 |
AVAudioSessionCategoryRecord | NO(鎖屏時依然保持錄製) | YES | 只輸入 |
AVAudioSessionCategorySoloAmbient | YES | YES | 只輸出 |
大部分應用只需要在啟動時設置一下 Category 即可,不過你是可以隨時修改 Audio Session 的 Category,也可以隨時激活和關閉 Audio Session。當你的 Audio Session 是 Inactive 的,Category 的請求會在你激活它時發送,如果是 Active 的,則立即發送。
選擇最合適的 Category
每一種 Category 最準確的行為定義是由系統控制而不是你的應用,蘋果可能會在將來重新定義不同的 Category 的行為,所以你最好是選擇一種與你的應用使用音頻方式匹配的 Category 來用。
下麵列一下各種 Category 的使用場景:
AVAudioSessionCategoryAmbient,只支持音頻播放。適用於把音頻作為輔助性元素而非不可獲取特性的應用,使用這個 Category,你的音頻會被靜音鍵和鎖屏鍵靜音。
AVAudioSessionCategorySoloAmbient,這個是預設使用的 Category,只支持音頻播放。音頻會被靜音鍵和鎖屏鍵靜音。這個 Category 和 AVAudioSessionCategoryAmbient 的唯一不同在於它會打斷其他應用的音頻播放。
AVAudioSessionCategoryPlayback,只支持音頻播放。你的音頻不會被靜音鍵和鎖屏鍵靜音。當你的應用把音頻播放作為重要功能時,你可以使用這個 Category。
有一點需要註意的是,當你選擇那些支持在靜音鍵切到靜音狀態以及鎖屏鍵切到鎖屏狀態下仍然支持你的音頻繼續播放的 Category 時,你必須在你的應用中開啟 Background Audio 的能力,詳見 UIBackgroundModes。並且,通常你不應該通過 idleTimerDisabled 介面關閉系統的 Sleep Timer。如果你關閉了,那你應該把 idleTimerDisabled 置回 NO,以免你的應用會禁止自動屏幕鎖定,畢竟鎖屏並不會影響你的音頻播放,你幹嘛關閉它呢。Sleep Timer 可以確保你的屏幕在用戶無操作一段時間後自動變暗並鎖定來省電。
- AVAudioSessionCategoryRecord,只支持音頻錄製。如果你的應用既要錄製還要播放,那你應該用 AVAudioSessionCategoryPlayAndRecord。
- AVAudioSessionCategoryPlayAndRecord,支持音頻播放和錄製。音頻的輸入和輸出不需要同步進行,當然也可以同步進行。對於音頻通話類應用,可以使用這個 Category。
- AVAudioSessionCategoryAudioProcessing,只支持離線音頻處理。支持離線音頻處理,並且不支持播放和錄製。
- AVAudioSessionCategoryMultiRoute,支持音頻播放和錄製。允許多條音頻流的同步輸入和輸出。比如:USB 和耳麥同時音頻輸出。
除了 AVAudioSessionCategoryMultiRoute 外,其他的 Category 都遵循 last in wins 原則,即最後接入的音頻設備作為輸入或輸出的主設備。
使用 AVAudioSessionCategoryMultiRoute 來擴展音頻選擇
AVAudioSessionCategoryMultiRoute 並不是簡單的遵循 last in wins 原則,AVAudioSessionCategoryMultiRoute 允許你的使用所有連接的輸出介面而不僅是最後連上的介面。比如,當你正在通過 HDMI 輸出路徑聽音頻,這時又插上了耳麥,你的應用可以同時在 HDMI 和耳麥都輸出音頻。
在 AVAudioSessionCategoryMultiRoute 下,你的應用可以發送不同的音頻流到不同的輸出路徑。例如,你的應用可以將一條音頻流發送到你的左耳麥,另一條音頻流發送到右耳麥,並將第三條流發送到 HDMI 路徑。如下圖所示:
AVAudioSessionCategoryMultiRoute 支持下列輸出組合:
- USB + 耳麥
- HDMI + 耳麥
- LineOut + 耳麥
AVAudioSessionCategoryMultiRoute 支持單輸入介面。
設置 Audio Session Category
代碼如下:
NSError *setCategoryError = nil;
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
// BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
if (!success) { /* handle the error in setCategoryError */ }
使用 Mode 來定製 Category
正如使用 Category 可以定製應用的音頻行為,我們使用 Mode 則可以定製 Category 的行為。可選的 Mode 有這些:
Mode | 相容的 Category |
---|---|
AVAudioSessionModeDefault | All |
AVAudioSessionModeVoiceChat | AVAudioSessionCategoryPlayAndRecord |
AVAudioSessionModeGameChat | AVAudioSessionCategoryPlayAndRecord |
AVAudioSessionModeVideoRecording | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord |
AVAudioSessionModeMoviePlayback | AVAudioSessionCategoryPlayback |
AVAudioSessionModeMeasurement | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback |
AVAudioSessionModeVideoChat | AVAudioSessionCategoryPlayAndRecord |
除了這些 Mode 外,有時在定製你的 Category 時,你還需要使用到一些 Option:
Option | 說明 | 相容的 Category |
---|---|---|
AVAudioSessionCategoryOptionMixWithOthers | 允許和其他音頻 mix | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute |
AVAudioSessionCategoryOptionDuckOthers | 智能調低衝突音頻音量 | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute |
AVAudioSessionCategoryOptionAllowBluetooth | 允許藍牙音頻輸入 | AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord |
AVAudioSessionCategoryOptionDefaultToSpeaker | 預設輸出音頻到揚聲器 | AVAudioSessionCategoryPlayAndRecord |
AVAudioSessionModeDefault,預設模式可以與所有的 Category 相容使用,並配置設備用於一般用途。
AVAudioSessionModeVoiceChat,一般用於 VoIP 類型的應用。這個模式只用於 AVAudioSessionCategoryPlayAndRecord Category。在這個模式下,用於音頻的信號會由系統提供的信號處理程式優化,並且這個模式會配置上 AVAudioSessionCategoryOptionAllowBluetooth 這個選項。這個設置下,當系統內置麥克風被使用時,系統會自動選擇最佳內置麥克風組合支持語音聊天,從而優化語音聊天體驗。
AVAudioSessionModeVideoChat,一般用於視頻聊天應用,比如 FaceTime。這個模式只用於 AVAudioSessionCategoryPlayAndRecord Category。在這個模式下,用於音頻的信號會由系統提供的信號處理程式優化,並且這個模式會配置上 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 選項。這個設置下,當系統內置麥克風被使用時,系統會自動選擇最佳內置麥克風組合支持視頻聊天,從而優化視頻聊天體驗。
蘋果推薦音頻或視頻聊天應用也使用 Voice-Processing I/O Unit,這個模塊提供了一系列的特性來支持 VoIP 類應用。
AVAudioSessionModeGameChat,一般用於游戲類應用。使用 GKVoiceChat 對象的應用會自動設置這個模式和 AVAudioSessionCategoryPlayAndRecord Category。這個模式使用的路徑參數和 AVAudioSessionModeVideoChat 一致。
AVAudioSessionModeVideoRecording,一般用於需要使用攝像頭採集視頻的應用。這個模式只用於 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord 這兩個 Category。在這個模式下,信號會被系統提供的信號處理程式修改。這個模式與 AVCaptureSession API 結合來用可以更好地控制音視頻的輸入輸出路徑。比如,通過設置 automaticallyConfiguresApplicationAudioSession 屬性可以讓系統根據所使用的設備自動選擇最佳輸出路徑。
AVAudioSessionModeMeasurement,一般用於那些要最小化系統自帶的音視頻信號處理流程對信號的影響的應用。這個模式只用於 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayback 這幾種 Category。輸入信號由設備的主麥克風來路由。
AVAudioSessionModeMoviePlayback,一般用於播放電影或其他視頻的應用。這個模式只用於 AVAudioSessionCategoryPlayback Category。
支持 AirPlay 的 Category 和 Mode
以下 Category 支持「鏡像」和「非鏡像」版本的 AirPlay:
- AVAudioSessionCategorySoloAmbient
- AVAudioSessionCategoryAmbient
- AVAudioSessionCategoryPlayback
此外:
- AVAudioSessionCategoryPlayAndRecord 只支持「鏡像」版本的 AirPlay。
Mode 只有在和 AVAudioSessionCategoryPlayAndRecord Category 配合使用時才支持 AirPlay,下麵的 Mode 只支持「鏡像」版本的 AirPlay:
- AVAudioSessionModeDefault
- AVAudioSessionModeVideoChat
- AVAudioSessionModeGameChat
Category 使用調優
你可以有多種方式來調優 Category,下麵舉幾個例子:
- 允許其他 App 的音頻與你的音頻 mix 在一起播放。你可以改寫 AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryMultiRoute 這些 Category 的中斷特性。改寫時,你需要應用 AVAudioSessionCategoryOptionMixWithOthers 選項到你的 Audio Session。如果你的應用是 mixable 的,當一個 non-mixable 應用的 Audio Session 被激活時,你的應用不會中斷它的音頻。同樣,你的應用的音頻在播放時也不會被其他 non-mixable 的應用中斷。
- 將音頻輸出路徑從聽筒改到揚聲器。當你使用 AVAudioSessionCategoryPlayAndRecord 這個 Category 時,音頻預設是從聽筒輸出的,你可以通過 overrideOutputAudioPort:error: 方法將音頻輸出路徑改到揚聲器。
- 當你的音頻播放時,你可以強制其他的音頻降低音量。這時候你需要將 AVAudioSessionCategoryOptionDuckOthers 應用到你的 Category 上,使用這個特性的應用需要管理自己的 Audio Session,在播放音頻前激活 Audio Session,在播放完成後關閉 Audio Session。
音頻錄製許可權申請
從 iOS7 之後,錄製音頻的許可權需要用戶授權才能獲得。如果用戶不給你許可權,那麼你錄製的就是靜音。當你使用一個需要錄製許可權的 Category 來定製你的 Audio Session 時,系統會自動彈出許可權申請提示給用戶。
除了讓系統自動彈出許可權申請提示外,你還可以通過 requestRecordPermission: 方法來向用戶請求許可權。