WWDC Quick Look 💓 By SwiftGGTeam
Record stereo audio with AVAudioSession

Record stereo audio with AVAudioSession

观看原视频

Highlight

iOS 14 和 iPadOS 14 让 AVAudioSession 能在支持的 iPhone 与 iPad 上从内建麦克风录制立体声,并通过 data source、stereo polar pattern 和 preferredInputOrientation 保持左右声道符合用户预期。

核心内容

手机录音以前经常少一层空间感。设备上明明有多个麦克风,App 录到的结果却常常按单声道处理。录演奏、采访、家庭视频或自拍视频时,听众只能知道声音存在,很难判断声音来自左边还是右边。

iOS 14 和 iPadOS 14 给 AVAudioSession 加入了内建麦克风立体声录音能力。系统会同时使用设备上的麦克风,并通过建模生成 binaural stereo(双耳立体声)体验。开发者不用直接控制每一颗麦克风,需要选择合适的输入 port、data source(数据源)、polar pattern(指向性模式)和输入方向。

这场 session 的关键点在“方向”。同一台 iPhone 可以竖着拿,也可以横着拿;可以用后置摄像头拍,也可以用前置摄像头拍。如果录音方向没有跟视频或界面方向对齐,画面左边的人说话,回放时声音可能从右边来。Apple 因此引入 inputOrientation,让 App 明确告诉系统当前录音应如何映射左右声道。

立体声录音也不是所有设备都能打开的固定开关。Session 要求开发者先选择内建麦克风,再检查 data source 是否支持 .stereo polar pattern;激活 session 后,还要读取实际的 input channel count(输入声道数)。这样,支持立体声的设备可以录到双声道,不支持的设备也能稳定降级到单声道。

详细内容

1. 先选中内建麦克风输入

06:57)配置立体声之前,App 先要把输入路由指向内建麦克风。演讲的代码从 availableInputs 里查找 .builtInMic,再调用 setPreferredInput

// How to set up recording from the built-in mic

private func enableBuiltInMic() {
    ...
    // Find the built-in microphone.
    guard let availableInputs = session.availableInputs,
          let builtInMic = availableInputs.first(where: { $0.portType == .builtInMic })
    else {
        print("The device must have a built-in microphone.")
        return
    }
    ...
    do {
        try session.setPreferredInput(builtInMic)
        ...
    } catch {
        ...
    }
}

关键点:

  • session.availableInputs 是当前可用输入 port 的入口,演讲要求先从这里找内建麦克风。
  • .builtInMic 过滤出设备自带麦克风,外接输入不会进入这个立体声录音配置。
  • guard 分支处理没有内建麦克风的设备,官方 snippet 直接打印提示并返回。
  • setPreferredInput(builtInMic) 对应 transcript 中“set that as our preferred input port”的步骤。

2. 为 data source 选择 stereo polar pattern

07:16)立体声录音使用的是新的 .stereo polar pattern。演讲提醒,只有支持立体声录音的设备才会出现这个 pattern,因此缓冲区大小不能写死,要在激活音频 session 后检查实际输入声道数。

// Configure stereo recording
func selectDataSource(...) {
    ...
    // Set the preferred polar pattern to stereo.
    try newDataSource.setPreferredPolarPattern(.stereo)

    // Set the preferred data source and polar pattern.
    try preferredInput.setPreferredDataSource(newDataSource)

    // Update the input orientation to match the current user interface orientation.
    try session.setPreferredInputOrientation(orientation.inputOrientation)
    ...
}

关键点:

  • newDataSource.setPreferredPolarPattern(.stereo) 请求 stereo polar pattern,只有支持的 data source 才能满足这个请求。
  • preferredInput.setPreferredDataSource(newDataSource) 决定前向聚焦方向,后置拍摄和前置拍摄应选择不同 data source。
  • session.setPreferredInputOrientation(...) 决定左右声道如何随设备方向映射。
  • 演讲建议激活 session 后检查 input channel count,再据此动态调整缓冲区。

3. 用 preferredInputOrientation 对齐左右声道

04:0605:06inputOrientation 有四个取值:portrait、portrait upside-down、landscape left、landscape right。再加上前向和后向两种 stereo data source,一共形成八种方向组合。

这里对应上一段官方 snippet 中的内联调用:try session.setPreferredInputOrientation(orientation.inputOrientation)

关键点:

  • data source 负责选择“前方”在哪里,例如后置摄像头方向或前置摄像头方向。
  • preferredInputOrientation 负责选择“左”和“右”如何对应设备边缘。
  • 录视频时,音频的左右应匹配视频画面左右。
  • 不录视频时,演讲建议让 stereo input orientation 匹配 UI orientation,因为用户会按界面方向理解设备。
  • 录入文件期间应保持方向固定,避免同一段录音里左右声道突然变化。

4. 用户改变界面或焦点时再更新 data source

08:22)示例 App 没有录视频,因此它在界面旋转或用户切换焦点方向时更新 data source。演讲明确提醒:正在录音时不要切换 data source 或 input orientation。

// When to select a data source & updated the stereo input orientation
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    updateDataSource()
}

@IBAction func updateDataSourceSelection(_ sender: Any) {
    updateDataSource()
}

private func updateDataSource() {
    // Don't update the data source if the app is currently recording.
    guard controller.state != .recording else { return }

    let dataSourceName = dataSources[dataSourceChooser.selectedSegmentIndex]
    controller.selectDataSource( named: dataSourceName,
        orientation:Orientation(windowOrientation)) { layout in
        self.layoutView.layout = layout
    }
}

关键点:

  • traitCollectionDidChange 覆盖界面方向变化,适合不录视频的录音 App。
  • updateDataSourceSelection 覆盖用户主动选择前向焦点的场景,例如选择前置或后置方向。
  • guard controller.state != .recording else { return } 保证录制过程中不改变声场方向。
  • Orientation(windowOrientation) 把当前窗口方向转换为音频输入方向。
  • 完成配置后,可以继续使用 AVAudioRecorderAVAudioEngine 做实际录音。

核心启发

1. 给自拍视频加方向正确的立体声

做什么:在相机 App 里根据前置或后置摄像头选择对应 stereo data source,并在开始录制前设置 input orientation。

为什么值得做:session 明确指出,录视频时音频左右应匹配画面左右,否则回放会让听众误判声源方向。

怎么开始:在用户按下录制按钮前,根据当前 camera position 和 video rotation 计算 data source 与 preferredInputOrientation,录制期间锁定这两个值。

2. 给纯音频采访 App 加“横竖屏声场”选项

做什么:让采访 App 在竖屏、横屏左、横屏右之间切换 stereo input orientation,并提示用户按当前界面方向摆放设备。

为什么值得做:不录视频时,Apple 建议让 stereo input orientation 匹配 UI orientation,这样用户对左右声道的理解最稳定。

怎么开始:监听界面方向变化,在未录音状态调用 data source 更新逻辑;录音开始后冻结方向,录音结束后再允许切换。

3. 给音乐练习 App 做立体声能力检测

做什么:启动录音前检测内建麦克风 data source 是否支持 .stereo,支持时录双声道,不支持时显示单声道状态。

为什么值得做:演讲提醒 .stereo 只会出现在支持硬件上,并建议激活 session 后读取实际 input channel count。

怎么开始:从 availableInputs.builtInMic,设置 preferred input 和 preferred data source;setActive 后按实际声道数配置 buffer 与录音文件格式。

4. 做一个左右声道自检向导

做什么:录音前引导用户先在设备左侧发声,再在右侧发声,回放后确认左右方向是否正确。

为什么值得做:session 建议对每个 orientation 和 data source 组合做全面测试,确认录到的方向符合预期。

怎么开始:把 App 支持的方向组合列成测试矩阵;每次测试录制几秒,保存声道峰值或让用户试听,发现异常就调整映射逻辑。

5. 给现场记录 App 加前向聚焦选择

做什么:让用户在“面向舞台”和“面向自己”两种录音焦点之间选择,分别对应后向和前向 stereo data source。

为什么值得做:演讲说明 data source 决定前向聚焦方向,前方声音会被增强,适合不同拍摄或记录姿态。

怎么开始:在录音前提供焦点选择器,选择后调用 setPreferredDataSourcesetPreferredInputOrientation;录音期间禁用选择器。

关联 Session

评论

GitHub Issues · utterances