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

iOS11中如何将AVCaptureVideoPreviewLayer旋转90度修正显示?

解决横屏应用中AVCaptureVideoPreviewLayer前置摄像头预览旋转90度的问题

嗨,这个问题我之前开发横屏相机应用时也碰到过!核心原因是AVCaptureSession的视频输出默认基于设备的自然竖屏方向,而你的应用处于横屏模式,再加上前置摄像头的镜像特性,就会出现画面偏移的情况。下面是具体的解决步骤和代码示例:

1. 基础设置:匹配视频方向与界面方向

首先,在初始化AVCaptureVideoPreviewLayer后,需要根据当前应用的横屏方向设置其connection的videoOrientation,同时为前置摄像头开启镜像:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let captureSession = AVCaptureSession()
    captureSession.sessionPreset = .high // 根据需求设置分辨率
    
    // 获取前置摄像头设备
    guard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) else {
        print("无法获取前置摄像头")
        return
    }
    
    // 添加输入到会话
    do {
        let input = try AVCaptureDeviceInput(device: captureDevice)
        if captureSession.canAddInput(input) {
            captureSession.addInput(input)
        }
    } catch {
        print("摄像头输入初始化失败:\(error)")
        return
    }
    
    // 创建预览层并添加到视图
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.frame = view.bounds
    previewLayer.videoGravity = .resizeAspectFill // 填充方式根据需求选择
    
    // 关键:设置视频方向为横屏,前置摄像头开启镜像
    if let connection = previewLayer.connection {
        if connection.isVideoOrientationSupported {
            // 假设你的应用是横屏右方向,可根据实际需求改为landscapeLeft
            connection.videoOrientation = .landscapeRight
            // 前置摄像头需要镜像,否则画面左右翻转不符合使用习惯
            if captureDevice.position == .front {
                previewLayer.mirroringMode = .horizontal
            }
        }
    }
    
    view.layer.addSublayer(previewLayer)
    
    // 启动会话
    captureSession.startRunning()
}

2. 处理界面方向变化(可选)

如果你的应用支持横屏方向切换(比如landscapeLeft和landscapeRight),需要在方向变化时同步更新预览层的方向:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    
    guard let previewLayer = view.layer.sublayers?.first as? AVCaptureVideoPreviewLayer,
          let connection = previewLayer.connection else {
        return
    }
    
    // 获取当前界面的实际方向
    let currentOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .portrait
    var videoOrientation: AVCaptureVideoOrientation
    
    switch currentOrientation {
    case .landscapeLeft:
        videoOrientation = .landscapeLeft
    case .landscapeRight:
        videoOrientation = .landscapeRight
    default:
        videoOrientation = .landscapeRight // 默认 fallback 到横屏右
    }
    
    // 仅在方向不匹配时更新,避免不必要的刷新
    if connection.isVideoOrientationSupported && connection.videoOrientation != videoOrientation {
        connection.videoOrientation = videoOrientation
        // 前置摄像头保持镜像设置
        if let input = previewLayer.session.inputs.first as? AVCaptureDeviceInput,
           input.device.position == .front {
            previewLayer.mirroringMode = .horizontal
        }
    }
    
    // 更新预览层frame适配视图大小变化
    previewLayer.frame = view.bounds
}

关键注意点

  • 前置摄像头的镜像:前置摄像头默认画面是镜像的,必须设置mirroringMode = .horizontal才能符合用户照镜子的使用习惯。
  • 视频方向的对应:AVCaptureVideoOrientation必须和应用的UIInterfaceOrientation完全匹配,否则会出现旋转或拉伸问题。
  • 会话启动时机:确保在设置好预览层的所有属性后再启动captureSession.startRunning(),避免画面闪烁或方向错误。

这样设置后,前置摄像头的预览画面就会和横屏应用的界面完全对齐,不会出现90度旋转的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:04:19