本文内容主要来自于:Configure an Audio Session
配置 Audio Session
对于 Audio Session 来说,Category 是识别应用程序的音频行为的关键因数。通过设置 Category,可以指出系统音频的意图,比如:当手机静音键切换时,你的App是否应该静音;你的 App 是否使用输入或输出;其它音频是否能和你的App音频混音等等。
每种 Category 对应下列的一种音频行为:
Interrupts nonmixable apps audio
如果 YES,当你的App音频激活时,中断不可混音的App音频Silenced by the Silent switch
如果 YES,当用户按下静音键时,你的 App 音频被静音
Supports audio input
如果 YES,你的 App 支持音频输入,也就是可以录音
Supports audio output
如果 YES,你的 App 支持音频输出,也就是可以播放
大多数 App 只需要在启动时设置一次 Category,但你可以根据需要设置 Audio Session 的 Category,可以在 Audio Session 激活时进行更改。但是,通常最好在更改 Category 或 其它属性之前,取消激活 Audio Session;在关闭时进行属性更改可以防止对音频系统进行不必要的重新配置。
Category 的作用表如下表:
Category | 当按下"静音键"或"锁屏"是否静音 | 是否中断不支持混音播放的App | 是否支持音频输入(录音)/音频输出(播放) |
---|---|---|---|
AVAudioSessionCategoryAmbient | YES | NO | 仅输出 |
AVAudioSessionCategorySoloAmbient(默认) | YES | YES | 仅输出 |
AVAudioSessionCategoryAudioProcessing | - | YES | 无输入和输出 |
AVAudioSessionCategoryPlayback | NO | 默认 YES,可重写开关置 NO | 仅输出 |
AVAudioSessionCategoryRecord | NO(锁屏时依然保持录制) | YES | 仅输入 |
AVAudioSessionCategoryPlaybackAndRecord | NO | 默认 YES,可重写开关置 NO | 输入和输出 |
AVAudioSessionCategoryMultiRoute | NO | YES | 输入和输出 |
注意🐽 :当你的应用程序继续播放音频时,Ring / Silent开关设置为静音并屏幕被锁定,请确保UIBackgroundModes音频键已添加到您的应用程序的Info.plist文件, 这个要求是你使用正确的类别。
下面列举一下 Category 使用场景:
AVAudioSessionCategoryAmbient
:只支持音频播放。适用于把音频作为辅助性元素而非不可获取特性的应用,使用这个 Category,你的音频会被静音键和锁屏键静音。
AVAudioSessionCategorySoloAmbient
:这个是默认使用的 Category,只支持音频播放。音频会被静音键和锁屏键静音。这个 Category 和 AVAudioSessionCategoryAmbient 的唯一不同在于它会打断其他应用的音频播放。
AVAudioSessionCategoryPlayback
:只支持音频播放。你的音频不会被静音键和锁屏键静音。当你的应用把音频播放作为重要功能时,你可以使用这个 Category。
AVAudioSessionCategoryRecord
:只支持音频录制。如果你的应用既要录制还要播放,那你应该用 AVAudioSessionCategoryPlayAndRecord。
AVAudioSessionCategoryPlayAndRecord
:支持音频播放和录制。音频的输入和输出不需要同步进行,当然也可以同步进行。对于音频通话类应用,可以使用这个 Category。
AVAudioSessionCategoryAudioProcessing
:只支持离线音频处理。支持离线音频处理,并且不支持播放和录制。
AVAudioSessionCategoryMultiRoute
:支持音频播放和录制。允许多条音频流的同步输入和输出。比如:USB 和耳麦同时音频输出。
使用 AVAudioSessionCategoryMultiRoute 扩展音频选择
除了 AVAudioSessionCategoryMultiRoute 外,其他的 Category 都遵循 "后来居上" (last in wins) 原则,即最后接入的音频设备作为输入或输出的主设备。
AVAudioSessionCategoryMultiRoute 能够使用所有连接的输出端口,而不是仅使用最后输入端口。比如,你正在通过 HDMI 路径听音频,这时再插入耳机,你的 App 可以同时通过 HDMI 和 耳机 输出音频。
使用 AVAudioSessionCategoryMultiRoute,你的应用程序也可以将不同的音频流发送到不同的输出路径。 例如,你的应用程序可以将一个音频流发送到左侧耳机,另一个发送到右侧耳机,另外一个发送到 HDMI 路径。
下图显示了将多个音频流发送到不同音频路径的示例:
AVAudioSessionCategoryMultiRoute 支持下列输出组合:
USB + 耳麦
HDMI + 耳麦
LineOut + 耳麦
设置 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 */ }
使用 Model 来定制 Category
正如使用 Category 可以定制应用的音频行为,我们使用 Mode 则可以定制 Category 的行为。可选的 Mode 有这些:
Model | 兼容 Category | 使用场景 |
---|---|---|
AVAudioSessionModelDefault | All | 默认 |
AVAudioSessionModelMoviePlayback | AVAudioSessionCategoryPlayback | 视频播放 |
AVAudioSessionModelVideoRecording | AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord | 录制视频 |
AVAudioSessionModelVoiceChat | AVAudioSessionCategoryPlayAndRecord | VoIP |
AVAudioSessionModelGameChat | AVAudioSessionCategoryPlayAndRecord | 游戏录制,由 GKVoiceChat 自动设置,无需手动调用 |
AVAudioSessionModelVideoChat | AVAudioSessionCategoryPlayAndRecord | 视频通话 |
AVAudioSessionModelMeasurement | AVAudioSessionCategoryPlayback、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord | 最小系统 |
除了这些 Mode 外,有时在定制你的 Category 时,你还需要使用到一些 Option:
Option | 适用的 Category | 作用 |
---|---|---|
AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryMultiRoute | 允许和其它音频混音 |
AVAudioSessionCategoryOptionDuckOthers | AVAudioSessionCategoryAmbient、AVAudionSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryMultiRoute | 智能调低冲突音频的音量 |
AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord | 允许蓝牙音频输入 |
AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryPlayAndRecord | 默认输出音频到扬声器 |
这些 Model 的具体使用:
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。
支持 AirPay 的 Model 和 Category
以下Category
支持 镜像
和 非镜像
版本的 AirPay:
AVAudioSessionCategorySoloAmbient
AVAudioSessionCategoryAmbient
AVAudioSessionCategoryPlayback
此外AVAudioSessionCategoryPlayAndRecord
仅支持 镜像
版本的AirPay。
以下Model
只有在和AVAudioSessionCategoryPlayAndRecord
配合使用才支持镜像
版本的 AirPay:
AVAudioSessionModeDefault
AVAudioSessionModeVideoChat
AVAudioSessionModeGameChat
注意🐽 :从iOS 10开始,您可以通过使用AVAudioSessionCategoryPlayAndRecord
类别激活与AVAudioSessionCategoryOptionAllowAirPlay
选项的会话来启用非镜像AirPlay输出。
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:
方法来向用户请求权限。