1. AVAudioSession 核心概念
AVAudioSession 是 Apple AVFoundation 框架中的一个核心类,用于管理 iOS、iPadOS 和 macOS 应用中的音频会话。它充当应用与操作系统(以及底层音频硬件)之间的中介,帮助应用声明其音频使用意图,从而允许系统协调多个应用的音频行为。例如,当应用播放声音时,它需要考虑其他应用(如音乐播放器)的音频输出、设备的静音开关、屏幕锁定状态等。
AVAudioSession 的主要目的是:
- 定义音频类别(Category),以指定应用的音频行为(如播放、录制或两者兼顾)。
- 配置模式(Mode)和选项(Options),以细化音频处理方式。
- 处理音频路由(Route),如切换到扬声器、耳机或蓝牙设备。
- 管理激活和中断(如来电中断音频播放)。
自 iOS 3.0 引入以来,AVAudioSession 不断演进。到 2025 年,它支持更多功能,如空间音频(Spatial Audio)、立体声录制和蓝牙 A2DP 支持的更新(例如,allowBluetooth 选项在 Xcode 26 中被标记为弃用)。
应用在使用 AVAudioSession 时,必须导入 AVFoundation 框架:
import AVFoundation
AVAudioSession 是单例设计,通过 AVAudioSession.sharedInstance() 获取实例。所有配置都应在主线程或适当的上下文中进行,以避免并发问题。
2. 使用方法概述
2.1 初始化和获取实例
AVAudioSession 是单例,无需手动初始化:
let audioSession = AVAudioSession.sharedInstance()
2.2 配置音频会话
配置主要通过设置类别、模式和选项完成。这些设置定义了应用的音频行为,例如是否允许与其他应用混合播放、是否忽略静音开关等。
-
设置类别(Category):使用
setCategory(_:mode:options:)方法。这是一个抛出异常的方法,因此需在 do-try-catch 块中使用。 示例:do { try audioSession.setCategory(.playback, mode: .default, options: []) } catch { print("设置类别失败: \(error)") }类别定义了音频的基本行为(如播放或录制)。从 Swift 4.2 开始,类别是结构体
AVAudioSession.Category,而非字符串常量。 -
设置模式(Mode):进一步细化类别,例如语音聊天模式。 示例:
try audioSession.setMode(.voiceChat) -
选项(Options):附加标志,如允许蓝牙或默认到扬声器。 示例:添加
.mixWithOthers以允许与其他应用混合音频。
2.3 激活和停用会话
激活会话以开始使用音频硬件:
do {
try audioSession.setActive(true)
} catch {
print("激活失败: \(error)")
}
- 使用
setActive(false)停用会话,以释放资源。 - 可选参数:
setActive(_:with:),如.notifyOthersOnDeactivation以通知其他应用。
激活失败常见原因包括权限不足或硬件冲突。应用应在需要音频时激活,并在完成后停用,以节省电池和资源。
2.4 处理权限
对于录制音频,需要请求麦克风权限:
audioSession.requestRecordPermission { granted in
if granted {
// 开始录制
} else {
// 处理拒绝
}
}
2.5 处理中断和路由变化
注册通知:
AVAudioSession.interruptionNotification:处理来电等中断。AVAudioSession.routeChangeNotification:处理耳机插入等路由变化。
示例:
NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil)
2.6 示例:播放音频忽略静音开关
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(.playback, mode: .default, options: [])
try session.setActive(true)
// 现在播放音频
} catch {
print(error)
}
3. 所有属性的意义
AVAudioSession 提供了众多只读和可设置属性,用于查询和配置音频状态。以下是完整列表,按功能分组。属性类型为 Swift 类型。
3.1 会话配置属性
-
category: AVAudioSession.Category
当前音频会话类别。只读,反映 setCategory 设置的值。意义:定义音频的基本用途,如 .playback(播放音乐,忽略静音开关)或 .record(仅录制)。 -
mode: AVAudioSession.Mode
当前模式。只读。意义:细化类别,例如 .voiceChat 用于 VoIP,支持回声消除。 -
categoryOptions: AVAudioSession.CategoryOptions
当前选项。只读。意义:附加行为,如 .allowBluetooth(允许蓝牙 A2DP,但已弃用)或 .mixWithOthers(允许与其他应用混合音频)。 -
availableCategories: [AVAudioSession.Category]
设备支持的类别列表。只读。意义:查询设备能力,例如某些设备不支持 .multiRoute。 -
availableModes: [AVAudioSession.Mode]
设备支持的模式列表。只读。意义:检查可用模式,如 .spatialAudio 用于空间音频。
3.2 路由和端口属性
-
currentRoute: AVAudioSession.RouteDescription
当前音频路由。只读。意义:描述输入/输出端口,如内置扬声器或耳机。包含 inputs 和 outputs 数组。 -
preferredInput: AVAudioSession.PortDescription?
首选输入端口。可设置。意义:指定首选麦克风,如外部设备。 -
availableInputs: [AVAudioSession.PortDescription]?
可用输入端口列表。只读。意义:列出所有麦克风端口,如内置麦克风或蓝牙。 -
inputDataSources: [AVAudioSession.DataSourceDescription]?
输入数据源列表。只读。意义:详细输入选项,如麦克风方向模式(.cardioid 用于定向拾音)。 -
inputDataSource: AVAudioSession.DataSourceDescription?
当前输入数据源。可设置。意义:选择特定数据源,如立体声录制。 -
outputDataSources: [AVAudioSession.DataSourceDescription]?
输出数据源列表。只读。意义:类似输入,但用于输出设备。 -
outputDataSource: AVAudioSession.DataSourceDescription?
当前输出数据源。可设置。意义:配置输出,如扬声器模式。
3.3 音频质量和性能属性
-
sampleRate: Double
当前采样率(Hz)。只读。意义:音频处理的采样频率,通常 44100 Hz。 -
preferredSampleRate: Double
首选采样率。可设置。意义:尝试设置自定义采样率,用于高质量录制。 -
inputNumberOfChannels: Int
输入通道数。只读。意义:如 1(单声道)或 2(立体声)。 -
outputNumberOfChannels: Int
输出通道数。只读。意义:类似输入,支持多通道音频。 -
preferredInputNumberOfChannels: Int
首选输入通道数。可设置。意义:请求立体声录制等。 -
preferredOutputNumberOfChannels: Int
首选输出通道数。可设置。意义:用于多通道播放。 -
inputGain: Float
当前输入增益(0.0-1.0)。只读。意义:麦克风灵敏度。 -
isInputGainSettable: Bool
是否可设置输入增益。只读。意义:检查硬件支持。 -
outputVolume: Float
当前输出音量(0.0-1.0)。只读。意义:系统音量级别。 -
inputLatency: TimeInterval
输入延迟(秒)。只读。意义:从麦克风到应用的延迟,用于实时音频。 -
outputLatency: TimeInterval
输出延迟(秒)。只读。意义:从应用到扬声器的延迟。 -
ioBufferDuration: TimeInterval
I/O 缓冲区持续时间(秒)。只读。意义:缓冲区大小,影响延迟。 -
preferredIOBufferDuration: TimeInterval
首选 I/O 缓冲区持续时间。可设置。意义:优化低延迟应用,如游戏。
3.4 状态和提示属性
-
isInputAvailable: Bool
是否有输入设备可用。只读。意义:检查麦克风存在。 -
promptStyle: AVAudioSession.PromptStyle
提示样式。只读。意义:如 .none 或 .short,用于系统提示音。 -
recordPermission: AVAudioSession.RecordPermission
录制权限状态。只读。意义:.granted、.denied 或 .undetermined。 -
secondaryAudioShouldBeSilencedHint: Bool
是否应静音次要音频。只读。意义:提示系统静音背景音频。 -
allowHapticsAndSystemSoundsDuringRecording: Bool
录制时允许触觉和系统声音。可设置。意义:允许录制期间的振动和系统音(iOS 13+)。 -
renderingMode: AVAudioSession.RenderingMode
渲染模式。只读。意义:如 .stereo 或 .spatialAudio,用于多通道或空间音频。 -
ioType: AVAudioSession.IOType
I/O 类型。只读。意义:.aggregated 或 .nonAggregated,用于 Live Photos 等(iOS 10+)。
4. 所有方法详解
以下是主要方法,按类别分组。所有抛出方法需 try-catch 处理。
4.1 配置方法
-
setCategory(_ category: AVAudioSession.Category, mode: AVAudioSession.Mode, options: AVAudioSession.CategoryOptions) throws
设置类别、模式和选项。意义:核心配置方法,用于定义音频行为。 -
setMode(_ mode: AVAudioSession.Mode) throws
单独设置模式。 -
setCategory(_ category: AVAudioSession.Category) throws
简化版本,仅设置类别(旧 API 兼容)。
4.2 激活方法
-
setActive(_ flag: Bool) throws
激活或停用会话。 -
setActive(_ flag: Bool, with options: AVAudioSession.SetActiveOptions) throws
带选项,如通知其他应用。
4.3 权限方法
- requestRecordPermission(_ response: @escaping (Bool) -> Void)
请求录制权限,异步回调。
4.4 首选设置方法
-
setPreferredSampleRate(_ sampleRate: Double) throws
设置首选采样率。 -
setPreferredIOBufferDuration(_ duration: TimeInterval) throws
设置首选缓冲区时长。 -
setPreferredInputNumberOfChannels(_ count: Int) throws
设置首选输入通道数。 -
setPreferredOutputNumberOfChannels(_ count: Int) throws
设置首选输出通道数。 -
setPreferredInput(_ inPort: AVAudioSession.PortDescription?) throws
设置首选输入端口。 -
setInputGain(_ gain: Float) throws
设置输入增益。 -
setInputDataSource(_ dataSource: AVAudioSession.DataSourceDescription?) throws
设置输入数据源。 -
setOutputDataSource(_ dataSource: AVAudioSession.DataSourceDescription?) throws
设置输出数据源。
4.5 路由控制方法
- overrideOutputAudioPort(_ portOverride: AVAudioSession.PortOverride) throws
覆盖输出端口,如强制到扬声器。
4.6 其他方法
- setAllowHapticsAndSystemSoundsDuringRecording(_ flag: Bool) throws
允许录制时触觉和系统音。
5. 相关常量、枚举和通知
-
AVAudioSession.Category:枚举,如 .ambient(环境音,可混合)、.soloAmbient(独占环境音)、.playback(播放)、.record(录制)、.playAndRecord(播放和录制)、.multiRoute(多路由)。
-
AVAudioSession.Mode:如 .default、.voiceChat、.videoRecording、.measurement(测量)。
-
AVAudioSession.CategoryOptions:位掩码,如 .duckOthers(降低其他音频)、.interruptSpokenAudioAndMixWithOthers、.allowAirPlay 等。
-
AVAudioSession.Port:端口类型,如 .builtInMic、.headphones、.bluetoothA2DP。
-
通知:
AVAudioSession.interruptionNotification:音频中断。AVAudioSession.routeChangeNotification:路由变化。AVAudioSession.mediaServicesWereLostNotification:媒体服务丢失。AVAudioSession.mediaServicesWereResetNotification:媒体服务重置。AVAudioSession.silenceSecondaryAudioHintNotification:次要音频静音提示。
6. 最佳实践
- 最佳实践:
- 在应用启动或需要音频时尽早配置会话。
- 处理异常:激活失败可能由于权限或冲突,使用日志记录错误。
- 监听通知:始终处理中断和路由变化,以恢复音频。
- 优化延迟:对于实时应用,设置较低的 preferredIOBufferDuration。
- 权限管理:在使用录制前检查 recordPermission。
- 后台音频:为播放添加 UIBackgroundModes 中的 audio 键。
- 测试不同设备:路由行为在 iPhone、iPad 和带蓝牙设备上不同。
枚举的详细解读
以下是对 AVAudioSession 中所有主要枚举的逐一解读,包括每个案例的意义和使用方法。这些枚举定义了音频会话的各种行为配置。
AVAudioSession.Category
音频类别定义了应用的音频用途和与其他应用的交互方式。使用 setCategory(_:mode:options:) 设置。默认是 .soloAmbient。
- .ambient:背景音频,受静音开关影响,不中断其他应用。意义:用于非关键音频,如游戏背景音。使用方法:适合混音场景,例如在播放音乐时添加音效。示例:
try session.setCategory(.ambient)。 - .soloAmbient(默认):独占背景音频,受静音开关影响,中断其他应用。意义:用于独占音频,但仍受设备静音控制。使用方法:适用于需要中断其他音频但尊重静音开关的应用,如简单游戏。
- .playback:播放音频,不受静音开关影响,支持后台播放。意义:用于媒体播放器,确保音频在静音模式下仍可播放。使用方法:启用后台音频模式,并在 Info.plist 中添加 UIBackgroundModes。示例:音乐 App。
- .record:仅录制音频。意义:专用于录音,不涉及播放。使用方法:结合 AVAudioRecorder,用于语音备忘录 App。
- .playAndRecord:同时播放和录制,支持耳机等。意义:用于 VoIP 或视频通话,支持双向音频。使用方法:允许蓝牙设备,示例:视频会议 App。
- .multiRoute:多路由音频输出。意义:支持多个输出设备,如 AirPlay 和 USB 接口。使用方法:用于专业音频应用,需要自定义路由。
AVAudioSession.Mode
模式进一步细化类别,优化特定场景。使用 setCategory(_:mode:options:) 设置。默认是 .default。
- .default:默认模式,无特殊优化。意义:适用于大多数场景。使用方法:作为通用模式,与任何类别兼容。
- .voiceChat:用于 VoIP 语音聊天。意义:优化延迟和回声消除。使用方法:结合
.playAndRecord,示例:电话 App。 - .videoChat:用于视频通话。意义:优化视频同步和音频质量。使用方法:如 FaceTime,支持视频录制。
- .gameChat:用于游戏语音聊天。意义:低延迟,适合实时游戏。使用方法:Game Kit 集成。
- .videoRecording:优化视频录制麦克风。意义:选择最佳麦克风(如后置)。使用方法:结合
.record或.playAndRecord,示例:相机 App。 - .measurement:用于音频测量。意义:最小信号处理,确保准确数据。使用方法:音频分析工具。
- .moviePlayback:优化电影播放。意义:增强信号处理,如动态范围。使用方法:视频播放器。
- .spokenAudio:用于有声书或播客。意义:允许暂停其他音频。使用方法:结合
.playback。 - .voicePrompt:用于文本到语音提示。意义:如 Siri,响应系统音频。使用方法:语音助手。
AVAudioSession.CategoryOptions
选项是位掩码,用于细化类别行为。使用 setCategory(_:mode:options:) 设置。
- .mixWithOthers:与他人混音。意义:允许与其他应用音频共存。使用方法:背景音乐 App。
- .duckOthers:压低他人音量。意义:使其他音频变安静。使用方法:导航 App 语音提示。
- .interruptSpokenAudioAndMixWithOthers:中断口语音频并混音。意义:暂停其他口语内容。使用方法:语音交互。
- .allowBluetooth:允许蓝牙设备。意义:支持蓝牙耳机(HFP 协议)。使用方法:VoIP。
- .allowBluetoothA2DP:允许蓝牙 A2DP(高品质)。意义:支持蓝牙立体声。使用方法:音乐播放。
- .allowAirPlay:允许 AirPlay。意义:无线投射。使用方法:媒体共享。
- .defaultToSpeaker:默认使用扬声器。意义:忽略接收器,使用内置扬声器。使用方法:免提通话。