You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用LivePhotoCapture时iPhone12内置超广角相机预览画面畸变

iPhone 12 超广角相机启用LivePhotoCapture时预览畸变问题解决建议

问题描述

在iPhone 12设备上,当为AVCapturePhotoOutput启用LivePhotoCapture并切换至builtInUltraWideCamera时,预览层画面右侧和底部边缘会出现畸变;禁用LivePhotoCapture后问题消失。该问题在iPhone 13 Pro上无法复现,调整videoGravity设置未解决问题。

相关代码

AVCapturePhotoOutput 配置代码

if self.photoOutput.isLivePhotoCaptureSupported {
    self.photoOutput.isLivePhotoCaptureEnabled = true
}

预览层配置代码

videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer.videoGravity = .resizeAspect
videoPreviewLayer.connection?.videoOrientation = .portrait
previewView.layer.addSublayer((videoPreviewLayer)!)

self.captureSession.startRunning()
self.videoPreviewLayer.frame = self.previewView.bounds

问题效果

画面右侧和底部边缘出现畸变(镜像为正常现象)

解决建议

  • 切换相机时重新触发LivePhoto配置
    iPhone 12的超广角相机与LivePhoto的兼容性存在场景化bug,建议切换到超广角相机时,先禁用LivePhotoCapture,切换完成后再重新启用:

    func switchToUltraWideCamera() {
        // 先关闭LivePhoto
        if self.photoOutput.isLivePhotoCaptureEnabled {
            self.photoOutput.isLivePhotoCaptureEnabled = false
        }
        
        // 执行超广角相机切换逻辑(替换captureSession的input)
        // ...
    
        // 延迟100ms后重新启用LivePhoto,确保相机切换完成
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            if self.photoOutput.isLivePhotoCaptureSupported {
                self.photoOutput.isLivePhotoCaptureEnabled = true
            }
            // 强制刷新预览层布局
            self.videoPreviewLayer.frame = self.previewView.bounds
            self.videoPreviewLayer.setNeedsDisplay()
        }
    }
    
  • 锁定会话预设与相机输出匹配
    为AVCaptureSession设置明确的会话预设,避免LivePhoto启用时自动调整分辨率导致适配异常:

    // 配置会话时设置预设为.photo,保证与相机输出匹配
    captureSession.sessionPreset = .photo
    
  • 延迟设置预览层Frame
    避免在会话启动后立即设置预览层Frame,等待会话完全初始化后再调整:

    self.captureSession.startRunning()
    DispatchQueue.main.async {
        self.videoPreviewLayer.frame = self.previewView.bounds
    }
    
  • 手动控制视频连接参数
    锁定相机输出的帧率,避免LivePhoto启用时帧率波动导致的畸变:

    if let connection = videoPreviewLayer.connection, connection.isVideoMinFrameDurationSupported {
        connection.videoMinFrameDuration = CMTimeMake(value: 1, timescale: 30)
        connection.videoMaxFrameDuration = CMTimeMake(value: 1, timescale: 30)
    }
    

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:25:22