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
相关产品推荐
相关产品推荐

