我有一个使用 AVFoundation 和 Swift 构建的自定义相机。当相机启动时,它最初会放大。大约一秒钟后,它会缩小到正常状态。我不确定为什么会发生这种情况,我根本不修改放大倍数,也不更改输入相机。也许我的 setup() 函数有问题。
struct CameraPreview: UIViewRepresentable {
@EnvironmentObject var cameraModel : CameraViewModel
var size: CGSize
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: CGRect(origin: .zero, size: size))
guard let preview = cameraModel.preview else { return view }
preview.frame = view.bounds
preview.videoGravity = .resizeAspectFill
view.layer.addSublayer(preview)
DispatchQueue.global(qos: .userInitiated).async {
if !self.cameraModel.session.isRunning {
self.cameraModel.session.startRunning()
}
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) { }
}
class CameraViewModel: NSObject, ObservableObject, AVCaptureFileOutputRecordingDelegate, AVCapturePhotoCaptureDelegate {
@Published var session = AVCaptureSession()
@Published var alert = false
@Published var output = AVCaptureMovieFileOutput()
@Published var preview: AVCaptureVideoPreviewLayer!
@Published var isRecording: Bool = false
@Published var recordedURLs: [URL] = []
@Published var previewURL: URL?
@Published var showPreview: Bool = false
@Published var recordedDuration: CGFloat = 0
@Published var maxDuration: CGFloat = 25
@Published var capturedImage: UIImage?
@Published var photoOutput = AVCapturePhotoOutput()
@Published var flashMode: AVCaptureDevice.TorchMode = .off
var currentCameraPosition: AVCaptureDevice.Position = .back
@Published var photoMode: Bool = true
@Published var isVideoFlashOn: Bool = false
override init() {
super.init()
self.checkPermission()
self.preview = AVCaptureVideoPreviewLayer(session: session)
self.preview.videoGravity = .resizeAspectFill
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
}
func checkPermission(){
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
checkAudioPermission()
return
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { (status) in
if status {
self.checkAudioPermission()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func checkAudioPermission() {
switch AVCaptureDevice.authorizationStatus(for: .audio) {
case .authorized:
setUp()
return
case .notDetermined:
AVCaptureDevice.requestAccess(for: .audio) { (audioStatus) in
if audioStatus {
self.setUp()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func setUp(){
do {
self.session.beginConfiguration()
let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
let audioDevice = AVCaptureDevice.default(for: .audio)
let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
self.session.addInput(videoInput)
self.session.addInput(audioInput)
}
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
if self.session.canAddOutput(self.photoOutput) {
self.session.addOutput(self.photoOutput)
}
self.session.commitConfiguration()
}
catch {
print(error.localizedDescription)
}
}
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
}
}
AVCaptureSession
或 AVCaptureDevice
的配置有关。
您可以尝试在会话开始时明确设置相机的缩放级别。如果支持缩放,可以通过调整
videoZoomFactor
的 AVCaptureDevice
属性来完成。
您的
setUp
功能将是:
func setUp(){
do {
self.session.beginConfiguration()
let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
let audioDevice = AVCaptureDevice.default(for: .audio)
let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
self.session.addInput(videoInput)
self.session.addInput(audioInput)
}
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
if self.session.canAddOutput(self.photoOutput) {
self.session.addOutput(self.photoOutput)
}
// Setting zoom level
try cameraDevice?.lockForConfiguration()
if cameraDevice?.activeFormat.videoMaxZoomFactor ?? 1 > 1 {
cameraDevice?.videoZoomFactor = 1 // Set this to your desired zoom level
}
cameraDevice?.unlockForConfiguration()
self.session.commitConfiguration()
}
catch {
print(error.localizedDescription)
}
}
我添加了一项检查以确保相机设备支持缩放,然后将
videoZoomFactor
设置为 1,这是正常的缩放级别。您可以根据需要调整该值。
请注意,操作
videoZoomFactor
需要锁定摄像头设备的配置,这就是使用 lockForConfiguration()
和 unlockForConfiguration()
的原因。