限时福利领取


在开发视频拍摄功能时,我们经常遇到自动对焦带来的困扰:比如拍摄人物访谈时,镜头突然对焦到背景导致主体模糊。今天就来聊聊如何用 AVFoundation 实现精准的手动对焦控制。

对焦效果对比

为什么需要手动对焦?

  1. 自动对焦的局限性
  2. 系统会自动寻找画面中对比度最高的区域对焦
  3. 无法在移动拍摄中保持固定焦点
  4. 容易受到光线变化干扰

  5. 专业场景需求

  6. 访谈视频需要锁定人物面部
  7. 产品展示需要固定对焦距离
  8. 特殊效果需要手动控制焦点转移

三种对焦模式对比

AVCaptureDevice 提供了三种对焦模式:

  • ContinuousAutoFocus:默认模式,持续自动调整
  • AutoFocus:单次自动对焦后锁定
  • Locked:完全手动控制模式

对焦模式示意图

实现手动对焦的五个关键步骤

  1. 检查设备支持

    guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, 
                                              for: .video, 
                                              position: .back) else { return }
    
    do {
        try device.lockForConfiguration()
        if device.isFocusModeSupported(.locked) {
            device.focusMode = .locked
        }
        device.unlockForConfiguration()
    } catch {
        print("锁定配置失败: \(error.localizedDescription)")
    }
  2. 设置对焦点坐标

  3. 坐标系是归一化的 (0,0) 到 (1,1)
  4. (0.5, 0.5) 表示画面中心

  5. 处理曝光联动

  6. 建议同时锁定曝光模式
  7. 避免对焦时出现亮度突变

  8. 添加KVO监听

    device.addObserver(self, 
                      forKeyPath: "adjustingFocus", 
                      options: .new, 
                      context: nil)
  9. 实现平滑过渡

  10. 使用 CATransaction 实现动画效果
  11. 控制对焦速度避免画面抽搐

常见问题解决方案

  1. iOS版本差异
  2. iOS 13+ 需要额外检查 isFocusPointOfInterestSupported
  3. 部分旧设备不支持所有对焦模式

  4. 内存泄漏预防

    deinit {
        device.removeObserver(self, forKeyPath: "adjustingFocus")
    }
  5. 性能优化建议

  6. 减少不必要的对焦操作
  7. 适当降低对焦精度可节省电量
  8. 长时间拍摄建议关闭实时对焦

完整代码示例

class FocusController: NSObject {
    private let device: AVCaptureDevice

    init(device: AVCaptureDevice) {
        self.device = device
        super.init()
        setupFocus()
    }

    private func setupFocus() {
        do {
            try device.lockForConfiguration()

            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = CGPoint(x: 0.5, y: 0.5)
            }

            if device.isFocusModeSupported(.autoFocus) {
                device.focusMode = .autoFocus
            }

            // 锁定曝光避免闪烁
            if device.isExposureModeSupported(.locked) {
                device.exposureMode = .locked
            }

            device.unlockForConfiguration()
        } catch {
            print("对焦配置错误: \(error)")
        }
    }

    func setFocus(point: CGPoint) {
        guard device.isFocusPointOfInterestSupported else { return }

        do {
            try device.lockForConfiguration()
            device.focusPointOfInterest = point
            device.focusMode = .autoFocus
            device.unlockForConfiguration()
        } catch {
            print("设置对焦点失败: \(error)")
        }
    }

    override func observeValue(forKeyPath keyPath: String?, 
                              of object: Any?, 
                              change: [NSKeyValueChangeKey : Any]?, 
                              context: UnsafeMutableRawPointer?) {
        if keyPath == "adjustingFocus" {
            // 对焦状态变化处理
        }
    }
}

进阶技巧:实现电影级拉焦效果

  1. 使用定时器逐步调整 focusPointOfInterest
  2. 配合曝光补偿实现景深变化
  3. 添加EaseInOut动画曲线让过渡更自然

手动对焦虽然增加了开发复杂度,但能为用户提供更专业的拍摄体验。建议在需要精准控制的场景中使用,普通拍摄还是保留自动对焦更方便。

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐