Discover advancements in iOS camera capture: Depth, focus, and multitasking
Media & Web 进阶 20m

探索 iOS 相机捕获的新进展:深度、对焦与多任务

Discover advancements in iOS camera capture: Depth, focus, and multitasking

2022年6月6日

在 Apple 官方观看视频

一句话判断

iOS 16 给 AVFoundation 的相机 API 带来三个关键更新:深度数据同步采集、手动对焦的精细化控制,以及在 iPad 分屏场景下保持相机预览的能力。

这场 Session 讲了什么

这个 Session 聚焦于 AVFoundation 相机捕获的三个具体改进方向,每一个都回应了开发者在实际项目中遇到的痛点。

深度数据采集的改进。 iOS 16 改进了深度数据(depth data)和照片的同步采集能力。之前获取深度图和对应的照片需要处理时间戳同步的问题,现在 API 提供了更可靠的方式确保深度数据和图像帧是精确匹配的。这对做背景虚化、3D 建模、AR 应用的开发者来说是好消息。

手动对焦控制。 新的 API 让开发者能更精细地控制镜头的对焦行为。你可以设置对焦的速率(从当前位置移动到目标位置的速度),也可以指定对焦的镜头位置。这对于专业摄影类 App 非常有用——用户想要精确控制焦点位置和拉焦速度(比如在视频拍摄中做平滑的焦点转换)。

iPad 多任务下的相机支持。 在 iPadOS 16 中,即使 App 不是全屏运行(比如在 Split View 或 Slide Over 模式下),相机预览也不会被中断。这意味着用户可以一边视频通话一边查资料,你的 App 的相机画面不会因为进入后台就黑屏。系统提供了相关的回调和 API 来帮助你处理这些场景。

值得深挖的点

深度数据的精度和性能平衡。 深度采集是一个计算密集型的操作。Session 讨论了在不同设备上深度数据的质量差异——配备 LiDAR 的设备(iPad Pro、iPhone Pro 系列)提供的深度数据精度远高于仅靠双摄或单摄做深度估计的设备。如果你的 App 依赖深度数据,需要对不同硬件能力做分级处理。

iPad 多任务对相机生命周期的改变。 以前相机的生命周期和 App 的前台状态绑定——App 进入后台,相机就停止。iPadOS 16 打破了这个假设。现在你的相机预览可能在一个很小的窗口里运行,用户还可能随时调整窗口大小。你需要处理各种尺寸变化和资源争抢的情况(比如两个 App 同时想用相机)。

代码片段

import AVFoundation

// 手动对焦控制
class CameraController: NSObject {
    let captureSession = AVCaptureSession()
    var videoDevice: AVCaptureDevice?
    
    func setupManualFocus() throws {
        guard let device = videoDevice else { return }
        try device.lockForConfiguration()
        
        // 切换到手动对焦模式
        device.focusMode = .locked
        
        // 设置对焦位置(0.0 = 最近,1.0 = 最远)
        device.setFocusModeLocked(lensPosition: 0.5) { timer in
            // 对焦完成的回调
        }
        
        device.unlockForConfiguration()
    }
    
    // 平滑拉焦
    func rampFocus(to position: Float, duration: CMTime) throws {
        guard let device = videoDevice else { return }
        try device.lockForConfiguration()
        
        device.focusMode = .locked
        device.setFocusModeLocked(lensPosition: position, completionHandler: nil)
        
        device.unlockForConfiguration()
    }
}

// 深度数据采集
func setupDepthCapture() {
    let photoOutput = AVCapturePhotoOutput()
    // 启用深度数据交付
    photoOutput.isDepthDataDeliveryEnabled = true
    
    let settings = AVCapturePhotoSettings()
    settings.isDepthDataDeliveryEnabled = true
    
    photoOutput.capturePhoto(with: settings, delegate: self)
}

// 在回调中获取深度数据
func photoOutput(_ output: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photo: AVCapturePhoto) {
    if let depthData = photo.depthData {
        let depthMap = depthData.depthDataMap
        // 使用深度图做后续处理
    }
}

最佳实践

  • 使用深度数据前检查 AVCaptureDevice.isDepthDataSupported,不是所有设备都支持。
  • 手动对焦时要给用户视觉反馈——比如显示当前的焦点位置和景深范围。
  • iPad 多任务场景下,监听 AVCaptureSessionisRunning 状态变化,在相机被系统回收时优雅降级。
  • 处理好深度数据的坐标系转换——深度图的像素和相机图像的像素不是简单的一一对应。

还有什么值得关注

  • 深度数据的格式有 kCVPixelFormat_DepthFloat16kCVPixelFormat_DepthFloat32 两种,精度和性能需要权衡。
  • iPad 上的 Stage Manager(台前调度)模式对相机 App 有额外的布局挑战,需要特别测试。
  • 如果你使用 SwiftUI 的 CameraPreview 方案,多任务下的生命周期管理需要额外处理。
  • 拉焦(focus pull)在视频拍摄中是一个高级需求,iOS 16 的 API 终于让它变得可行。
WWDC 2022