|
发表于 2021-8-22
|
|阅读模式
音频输出作为硬件资源,对于iOS系统来说是唯一的,需要通过“AVAudioSession”这个系统级全局对象对各个App进行控制。 ( G4 p7 G3 r, `, O7 W
+ h, M2 @6 h7 f. S
; ~6 {! H; ]" ~6 Z4 g' j" [; R
控制路程如下图:
% L7 v. Y7 t# c
$ c2 f' i! a. v8 w- Y# T# n
( F: ^0 c2 S/ n( M7 p0 s
/ m: n& `) q, e2 g
常见音频场景' H" s3 r4 a, }/ w
1 s) M% {* P2 T" J4 J3 U; a
2 k# b: n* b! m6 |$ B5 S$ Y6 m1 h是进行录音还是播放? 当系统静音键按下时该如何表现? 是从扬声器还是从听筒里面播放声音? 插拔耳机后如何表现? 来电话/闹钟响了后如何表现? 其他音频App启动后如何表现? ! s: b8 T* P, I* K( q/ z" g& O
# t% w* G& z5 B" q% c9 m" R2 s8 r
9 m0 d! _6 a2 v2 s6 Y. p( r3 ^! C6 x) M
通过“AVAudioSession”可以做什么操作; U0 a. C( I; a/ p" }6 k% v
4 H+ m0 P! d% m8 i4 O) l" `
3 u% O7 @" {" U. _! l: g& m
为app选择输入输出的路由:通过扬声器或者听筒播放--可以手动设置通过手机上扬声器/听筒或者耳机播放--系统自动切换,插入耳机默认耳机 为app选择输入的路由:通过手机麦克风或者耳机麦克风采集-系统自动切换,插入耳机默认耳机 协调音频播放的app之间的关联,以及系统的声音处理 处理被其他app打断后的情况 录音或者播放音乐
" z7 O* ~2 O4 x9 ] % u9 m, O$ M/ {8 c
5 W' x' {) P5 J7 g$ `& b
* [" v9 g# u' o& i0 R# uAVAudioSession默认行为1 M" N3 A3 E, W* d8 L+ o; e
& Z2 q* N3 j8 T# Z4 ]
$ S0 H% {% l% {# k, M5 I可以进行播放,但是不能进行录制。 当用户将手机上的静音拨片拨到“静音”状态时,此时如果正在播放音频,那么播放内容会被静音。 当用户按了手机的锁屏键或者手机自动锁屏了,此时如果正在播放音频,那么播放会静音并被暂停。 如果你的App在开始播放的时候,此时QQ音乐或其他App正在播放,那么其他播放器会被静音并暂停。
1 P1 z7 R! F# d% f5 Z & p% n* D6 z0 g% s
5 ?- ^( Z/ `$ Z# [' v/ o' ~- r4 _; `% h0 |- Y; o3 A
系统会在app启动的时候,激活这个全局唯一的AVAudioSession
) j( B8 x# V2 E! [% ~3 |9 ^' Y
* q* f* h. V+ @. K$ D/ q: c s
- U/ T3 o4 h6 ~" `0 u) H2 \音频模式七大场景2 f1 V# V* U8 u q8 _' F" R
* ^# n" D" W) @& |( o4 L9 I( g
: t" Z2 l- F, c, z" K6 A" X2 C, k
该场景由7个类别分别控制: 6 r# p" o3 S; |# H1 ^' l4 f9 A8 f
" {+ q- e" J& Q+ S2 g$ Y
) E) O1 _' o; \& G+ z. s4 s2 r; Y$ V默认是:CategorySoloAmbient(独占播放)
# E/ [1 u; R! _1 W4 D- e* E% b8 V$ b2 d
/ G; @% g6 x: D7 zAVAudioSessionCategoryAmbient : 只用于播放音乐时,并且可以和QQ音乐同时播放,比如玩游戏的时候还想听QQ音乐的歌,那么把游戏播放背景音就设置成这种类别。同时,当用户锁屏或者静音时也会随着静音,这种类别基本适用所有App的背景场景。 AVAudioSessionCategorySoloAmbient: 也是只用于播放,但是和"AVAudioSessionCategoryAmbient"不同的是,用了它就别想听QQ音乐了,比如不希望QQ音乐干扰的App,类似节奏大师。同样当用户锁屏或者静音时也会随着静音,锁屏了就玩不了节奏大师了。 AVAudioSessionCategoryPlayback: 如果锁屏了还想听声音怎么办?用这个类别,比如App本身就是播放器,同时当App播放时,其他类似QQ音乐就不能播放了。所以这种类别一般用于播放器类App AVAudioSessionCategoryRecord: 有了播放器,肯定要录音机,比如微信语音的录制,就要用到这个类别,既然要安静的录音,肯定不希望有QQ音乐了,所以其他播放声音会中断。想想微信语音的场景,就知道什么时候用他了。 AVAudioSessionCategoryPlayAndRecord: 如果既想播放又想录制该用什么模式呢?比如VoIP,打电话这种场景,PlayAndRecord就是专门为这样的场景设计的 。 AVAudioSessionCategoryMultiRoute: 想象一个DJ用的App,手机连着HDMI到扬声器播放当前的音乐,然后耳机里面播放下一曲,这种常人不理解的场景,这个类别可以支持多个设备输入输出。 AVAudioSessionCategoryAudioProcessing: 主要用于音频格式处理,一般可以配合AudioUnit进行使用
3 O/ l8 y* C$ p: b |$ Q! b% t9 {' y9 R7 J
& t! {6 Z& P9 y2 f( i/ l, z1 i: o2 r, p
上面介绍的七大类别,可以认为是设定了七种主场景,而这七类肯定是不能满足开发者所有的需求的。AVAudioSession提供的方法是,首先定下7种类别中的一种基调,再进行微调。AVAudioSession为每种Category都提供了些许选项来进行微调。 6 C, C% V! ?/ X2 @* e8 `7 {: N
1 E% e$ _' w1 @8 x7 H' e1 ?
9 |# G3 X, M' [ q类别的选项 c$ @3 o% u+ Y
8 Y7 E/ Z4 c: Q" h% l8 @: k: k
' O3 f1 C Y8 S8 u0 s5 Y [AVAudioSessionCategoryOptionMixWithOthers : 如果确实用的AVAudioSessionCategoryPlayback实现的一个背景音,但是又想和QQ音乐并存,可以在AVAudioSessionCategoryPlayback类别下在设置这个选项,就可以实现共了。 AVAudioSessionCategoryOptionDuckOthers:在实时通话的场景,比如QQ音乐,当进行视频通话的时候,会发现QQ音乐自动声音降低了,此时就是通过设置这个选项来对其他音乐App进行了压制。 AVAudioSessionCategoryOptionAllowBluetooth:如果要支持蓝牙耳机电话,则需要设置这个选项 AVAudioSessionCategoryOptionDefaultToSpeaker: 如果在VoIP模式下,希望默认打开免提功能,需要设置这个选项
! X7 \$ ~; Z1 @& Z+ h
6 l, G9 i2 b" Q7 G1 E- J' O. X8 I( s( Y
2 M! |4 M' c( \6 ^七大模式8 Y. W2 e5 {7 c. X8 S
0 h) B" a1 R( E+ d4 N
0 v+ |$ |, T- A8 j
AVAudioSessionModeDefault: 每种类别默认的就是这个模式。 AVAudioSessionModeVoiceChat:主要用于VoIP场景,此时系统会选择最佳的输入设备,比如插上耳机就使用耳机上的麦克风进行采集。同时会设置类别的选项为"AVAudioSessionCategoryOptionAllowBluetooth"从而支持蓝牙耳机。 AVAudioSessionModeVideoChat : 主要用于视频通话,比如QQ视频、FaceTime。系统会选择最佳的输入设备,比如插上耳机就使用耳机上的麦克风进行采集并且会设置类别的选项为"AVAudioSessionCategoryOptionAllowBluetooth" 和 "AVAudioSessionCategoryOptionDefaultToSpeaker"。 AVAudioSessionModeGameChat : 适用于游戏App的采集和播放,比如“GKVoiceChat”对象,一般不需要手动设置 * I) j$ _9 c8 J |) j
/ B- b3 t# s/ T; s2 h7 b2 J
' r8 q7 ^' E% [9 m8 [( r$ H. `0 U& u" @9 e/ O5 w" ~) r; M% h4 W) ?
每个模式有其适用的类别,可以根据具体需要做对应的组合。 ! c+ f- }; U: k: m) @ y) a+ I) T+ W9 V
: g3 {4 l, s5 _ e1 i
! S( M. {1 q% B# j+ |音频通知" n5 M/ {0 q4 j% z9 j$ a. v( T
. x5 [7 `! I1 ^
: }. e; A. D- R7 j% V
系统中断通知
3 ~- p8 h. C2 y2 q7 v5 }9 V
2 _5 W- x1 T/ a$ V+ m6 E8 l! t' S
如果app正在视频通话,突然来电话了、闹钟响了等,最常用的场景是先暂停,待恢复的时候再继续。app可以通过监听系统消息:AVAudioSessionInterruptionNotification来处理。系统消息userInfo主要包含两个键:
* |: W6 \& {* E# e% }8 j: U6 R' Y2 I) S7 s7 M3 A
t% K v6 g0 A& A0 d/ q! s
AVAudioSessionInterruptionTypeKey: 取值为AVAudioSessionInterruptionTypeBegan表示中断开始,我们应该暂停播放和采集,取值为AVAudioSessionInterruptionTypeEnded表示中断结束,我们可以继续播放和采集。 AVAudioSessionInterruptionOptionKey: 当前只有一种值AVAudioSessionInterruptionOptionShouldResume表示此时也应该恢复继续播放和采集。
8 Y: T# i& I) B% X! |
- J, {$ G# I+ C/ A
6 M$ z9 X( _; e" _3 B2 [2 p1 F" r$ b' E0 B7 c `' e1 E8 u
其他app占用通知, K' n7 [1 v- p$ h0 t% V
) Y1 P- P$ t7 T5 I2 H8 w" a
8 P3 C* d8 k$ q其他App占据AudioSession的时候用AVAudioSessionSilenceSecondaryAudioHintNotification来进行通知。其回调回来的userInfo键为:AVAudioSessionSilenceSecondaryAudioHintTypeKey
( S% m. \$ d0 T, l9 j9 C( V% p; o& G- E% a/ X
]' V- q" `* q; Q0 r
0 \, g" X" I, P" Y" r
: o* W0 ~' y9 W; A: h
2 N; \& H8 N6 x9 ?4 `/ j, i
外设改变通知# M! B7 w) b5 I! T
" M$ z- E4 c1 E/ B6 H' d; L+ o' `. C; G4 v# X
默认情况下,AVAudioSession会在App启动时选择一个最优的输出方案,比如插入耳机的时候,就用耳机。但是这个过程中,用户可能拔出耳机,app可以通过监听系统消息:AVAudioSessionRouteChangeNotification来处理。
5 Y% V3 F' @1 l
* K3 @7 I% o& q* r$ `) g, |0 g3 u% d" L W" e( p& k0 ^
针对视频通话场景设置
" x4 T1 O3 s6 m5 H5 ]- b) k/ t
; l6 @% U: f( z2 ~ ^4 |% x
: o5 C( }: v* t0 ~# M+ ]6 r类别:AVAudioSessionCategoryPlayAndRecord类别的选项:AVAudioSessionCategoryOptionAllowBluetoothAVAudioSessionCategoryOptionDefaultToSpeaker模式:AVAudioSessionModeVideoChat & R" g, P# s! D3 {7 _9 R
+ }2 s$ T6 m) T' j! c% C, C. f9 O7 D% s* o) S) J* ~+ c
如果想做录制一段音频,然后进行播放的操作。
. ]. J. ?9 K5 h4 j
* d! n0 X U" {* [
6 `- p, F* f( Y8 @- a) a% P5 _2 ?建议录音修改为:(也就是支持录音的模式)
7 s/ G, l) N+ N" E* E/ C+ B2 Q7 D/ u& G
+ R B" C% G/ i2 z+ a
5 }+ B2 o2 x% e% V6 Q
建议播放修改为:(也就是只播放的模式)。经过我的测试,播放时使用AVAudioSessionCategoryPlayAndRecord(录音播放模式),会导致播放声音很小。
8 q0 D% W* R! d5 n2 h1 ^& ]5 I
9 i6 Y! c% }6 T; ]5 r S% k8 |9 F# W4 g
AVAudioSessionCategorySoloAmbient 或 AVAudioSessionCategoryAmbient 或AVAudioSessionCategoryPlayback
5 t6 |( t; C/ J; M! ~
2 J4 _" Z @. C$ u6 w
+ y, s6 @) L0 i! O; ]
+ k G1 B) @* } |
|