探索 iOS 相机捕获的新进展:深度、对焦与多任务
Discover advancements in iOS camera capture: Depth, focus, and multitasking
2022年6月6日
一句话判断
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 多任务场景下,监听
AVCaptureSession的isRunning状态变化,在相机被系统回收时优雅降级。 - 处理好深度数据的坐标系转换——深度图的像素和相机图像的像素不是简单的一一对应。
还有什么值得关注
- 深度数据的格式有
kCVPixelFormat_DepthFloat16和kCVPixelFormat_DepthFloat32两种,精度和性能需要权衡。 - iPad 上的 Stage Manager(台前调度)模式对相机 App 有额外的布局挑战,需要特别测试。
- 如果你使用 SwiftUI 的
CameraPreview方案,多任务下的生命周期管理需要额外处理。 - 拉焦(focus pull)在视频拍摄中是一个高级需求,iOS 16 的 API 终于让它变得可行。