如何在RTCCameraVideoCapturer中调整分辨率比例至1334*750?
调整AVCaptureDevice.Format到1334×750并实现全屏预览的方案
嘿,我来帮你搞定这个AVCapture预览的问题。首先得明确一点:AVCaptureDevice的可用格式是由硬件决定的,不是你想设什么分辨率就能直接设的,所以我们分两种情况来处理:
一、先检查设备是否原生支持1334×750的格式
1334×750是标准16:9的宽高比(计算一下:750 × 16/9 ≈ 1333.33,和1334几乎一致),你可以先遍历设备的可用格式,看看有没有匹配的:
import AVFoundation func findDesiredFormat(for device: AVCaptureDevice) -> AVCaptureDevice.Format? { let desiredWidth = 1334 let desiredHeight = 750 let desiredAspectRatio = CMVideoFormatDescriptionGetAspectRatio(CMVideoFormatDescriptionCreateForImageBuffer(nil, Int32(desiredWidth), Int32(desiredHeight), kCVPixelFormatType_32BGRA, nil)!) for format in device.formats { let formatDesc = format.formatDescription let dimensions = CMVideoFormatDescriptionGetDimensions(formatDesc) let aspectRatio = CMVideoFormatDescriptionGetAspectRatio(formatDesc) // 检查宽高是否完全匹配,或者比例一致且分辨率非常接近 if (dimensions.width == Int32(desiredWidth) && dimensions.height == Int32(desiredHeight)) || (aspectRatio.width == desiredAspectRatio.width && aspectRatio.height == desiredAspectRatio.height && abs(dimensions.width - Int32(desiredWidth)) < 10) { return format } } return nil }
如果调用这个方法能返回非空的格式,那直接把它设置给你的AVCaptureDeviceInput就行:
guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return } do { let input = try AVCaptureDeviceInput(device: device) if let desiredFormat = findDesiredFormat(for: device) { try device.lockForConfiguration() device.activeFormat = desiredFormat // 顺便可以设置帧率,比如30fps保证流畅度 device.activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: 30) device.activeVideoMaxFrameDuration = CMTimeMake(value: 1, timescale: 30) device.unlockForConfiguration() } // 把input添加到你的AVCaptureSession中... } catch { print("设置设备失败:\(error.localizedDescription)") }
二、如果设备不支持原生1334×750格式,怎么适配全屏预览
如果找不到刚好匹配的格式,不用慌,我们可以通过预览层的缩放策略来实现全屏填充,效果完全能满足需求:
- 首先选择一个和1334×750同比例(16:9)的最高分辨率格式,这样预览画质不会打折扣;
- 然后给
AVCaptureVideoPreviewLayer设置合适的videoGravity:.resizeAspectFill:会自动拉伸/裁剪画面,让整个预览层被填满,没有黑边,适合全屏需求(边缘少量画面会被切掉,不影响大部分场景);.resizeAspect:严格保持画面比例,会在预览层上下或左右留黑边,画面完整但不全屏;- 如果你需要极致精确的1334×750适配,还可以手动调整预览层的frame,或者结合CoreImage对捕获的帧进行二次缩放(不过一般用
videoGravity就足够了)。
示例代码设置预览层:
let previewLayer = AVCaptureVideoPreviewLayer(session: yourCaptureSession) previewLayer.frame = yourFullScreenView.bounds // 选择全屏填充模式 previewLayer.videoGravity = .resizeAspectFill // 别忘了设置视频方向,匹配1334×750的横屏需求 if let connection = previewLayer.connection { if connection.isVideoOrientationSupported { connection.videoOrientation = .landscapeRight // 根据你的界面方向调整 } } yourFullScreenView.layer.addSublayer(previewLayer)
关键注意点
- 1334×750是横屏分辨率,竖屏对应的是750×1334,所以一定要确保预览层的
videoOrientation和你期望的方向一致,不然画面会变形; - 部分设备可能不支持1334×750这种非标准的16:9分辨率(比如高端设备只支持1920×1080、3840×2160等),这时候用同比例的高分辨率格式+预览层缩放是最优解,画质反而比原生1334×750更好。
内容的提问来源于stack exchange,提问作者oldold
相关产品推荐
相关产品推荐

