首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS Swift AVFoundation每次录制AVCaptureMovieFileOutput isRecording值错误

iOS Swift AVFoundation每次录制AVCaptureMovieFileOutput isRecording值错误
EN

Stack Overflow用户
提问于 2020-07-22 06:51:39
回答 1查看 793关注 0票数 0

我试图记录和保存视频使用AVFoundation框架与前后摄像头。我能够启动会话,但无法将视频记录保存在文档目录中。我每次都检查movieOutput.isRecording,它给了false。因此,也没有调用委托输出方法。即使在开始记录时也不调用开始委托。

代码语言:javascript
运行
复制
import UIKit
import Foundation
import AVKit
import AVFoundation

class AppVideoRecorder: NSObject {
    
    private var session = AVCaptureSession()
    private var movieOutput = AVCaptureMovieFileOutput()
    private var camera: AVCaptureDevice?
    private var activeInput: AVCaptureDeviceInput?
    private var previewLayer = AVCaptureVideoPreviewLayer()
    
    private var renderView: UIView!
    var isFrontCamera: Bool = false
    
    init(for view: UIView) {
        self.renderView = view
    }
    
    deinit {
        print("Called")
    }
    
    func setupSession() {
        
        self.session.sessionPreset = .high
       
        // Setup Camera
        self.camera = AVCaptureDevice.default(
            .builtInWideAngleCamera,
            for: .video,
            position: self.isFrontCamera ? .front : .back
        )
                
        if let camera = self.camera {
            do {
                let input = try AVCaptureDeviceInput(device: camera)
                if self.session.canAddInput(input) {
                    self.session.addInput(input)
                    self.activeInput = input
                }
            } catch {
                print(error)
            }
        }
        
        // Setup Microphone
        if let microphone = AVCaptureDevice.default(for: .audio) {
            do {
                let micInput = try AVCaptureDeviceInput(device: microphone)
                if self.session.canAddInput(micInput) {
                    self.session.addInput(micInput)
                }
            } catch {
                print(error)
            }
        }
        
        // Movie output
        if self.session.canAddOutput(self.movieOutput) {
            self.session.addOutput(self.movieOutput)
        }
    }
    
    func setupPreview() {
        // Configure previewLayer
        self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
        self.previewLayer.frame = self.renderView.bounds
        self.previewLayer.videoGravity = .resizeAspectFill
        self.renderView.layer.addSublayer(self.previewLayer)
    }
    
    func startSession() {
        if self.session.isRunning { return }
        DispatchQueue.main.async {
            self.session.startRunning()
        }
    }
    
    func stopSession() {
        if self.session.isRunning {
            DispatchQueue.main.async {
                self.session.stopRunning()
            }
        }
    }
    
    func removeInput() {
        guard let input = self.activeInput else { return }
        self.session.removeInput(input)
    }
 
    func isCameraOn(completion: @escaping (Bool) -> Void) {
        if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
            completion(true)
        } else {
            AVCaptureDevice.requestAccess(for: .video,
                                          completionHandler: { (granted) in
                completion(granted)
            })
        }
    }
    
    func toggleCamera() {
        
        self.session.beginConfiguration()
                
        for input in self.session.inputs {
            if let inputObj = input as? AVCaptureDeviceInput {
                self.session.removeInput(inputObj)
            }
        }
        
        self.camera = AVCaptureDevice.default(
            .builtInWideAngleCamera,
            for: .video,
            position: self.isFrontCamera ? .front : .back
        )

        if let camera = self.camera {
            do {
                let input = try AVCaptureDeviceInput(device: camera)
                if self.session.canAddInput(input) {
                    self.session.addInput(input)
                    self.activeInput = input
                }
            } catch {
                print(error)
            }
        }

        self.session.commitConfiguration()
    }
    
}

extension AppVideoRecorder: AVCaptureFileOutputRecordingDelegate {
    
    private var currentVideoOrientation: AVCaptureVideoOrientation {
         var orientation: AVCaptureVideoOrientation

         switch UIDevice.current.orientation {
         case .portrait:
             orientation = AVCaptureVideoOrientation.portrait
         case .landscapeRight:
             orientation = AVCaptureVideoOrientation.landscapeLeft
         case .portraitUpsideDown:
             orientation = AVCaptureVideoOrientation.portraitUpsideDown
         default:
             orientation = AVCaptureVideoOrientation.landscapeRight
         }

         return orientation
     }
    
    func recordVideo() {
        if self.movieOutput.isRecording { // FALSE EVERY TIME
           self.stopRecording()
        } else {
            self.startRecording()
        }
    }
    
    private func startRecording() {
        
        guard let connection = self.movieOutput.connection(with: .video),
            let device = self.activeInput?.device else { return }
        // handle return error

        if connection.isVideoOrientationSupported {
            connection.videoOrientation = self.currentVideoOrientation
        }
        
        if connection.isVideoStabilizationSupported {
            connection.preferredVideoStabilizationMode = .auto
        }

        if device.isSmoothAutoFocusSupported {
            do {
                try device.lockForConfiguration()
                device.isSmoothAutoFocusEnabled = false
                device.unlockForConfiguration()
            } catch {
                print("Error setting configuration: \(error)")
            }
            
        }
        
        let paths = FileManager.default.urls(for: .documentDirectory,
                                             in: .userDomainMask)
        guard let path = paths.first else { return }
        let fileUrl = path.appendingPathComponent("celeb_video.mp4")
        try? FileManager.default.removeItem(at: fileUrl)
        
        self.movieOutput.startRecording(to: fileUrl, recordingDelegate: self)
    }
    
    private func stopRecording() {
        self.movieOutput.stopRecording()
    }
    
    func fileOutput(_ output: AVCaptureFileOutput,
                    didFinishRecordingTo outputFileURL: URL,
                    from connections: [AVCaptureConnection],
                    error: Error?) {
        print("DELEGATE CALL BACK")
        if let error = error {
            //do something
            print(error)
        } else {
            //do something
            print(outputFileURL.path)
            //            UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path, nil, nil, nil)
        }
    }

    func fileOutput(_ output: AVCaptureFileOutput,
                didStartRecordingTo fileURL: URL,
                from connections: [AVCaptureConnection]) {
    print("didStartRecordingTo CALL BACK:", fileURL.path)
}

}

这是我在视图控制器中的调用代码。recordingViewUIView

代码语言:javascript
运行
复制
private lazy var recorder: AppVideoRecorder = {
    return AppVideoRecorder(for: self.recordingView)
}()

@IBAction func recordingAction(_ sender: UIButton) {
    sender.isSelected.toggle()
    if sender.isSelected {
        self.recorder.setupSession()
        self.recorder.setupPreview()
        self.recorder.startSession()
        self.recorder.recordVideo()
    } else {
        self.recorder.recordVideo()
        self.recorder.removeInput()
        self.recorder.stopSession()
    }
}

@IBAction func swapCameraAction(_ sender: UIButton) {
    sender.isSelected.toggle()
    self.recorder.isFrontCamera = sender.isSelected
    self.recorder.toggleCamera()
}

请告诉我我错过了什么。

EN

回答 1

Stack Overflow用户

发布于 2020-07-22 09:57:04

来自链接Starting video recording immediately with AVCaptureMovieFileOutput

我已经添加了通知,现在它正在工作,因为它需要时间来启动。

代码语言:javascript
运行
复制
private func setupNotifications() {
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(sessionDidStartRunning(_:)),
                                           name: .AVCaptureSessionDidStartRunning,
                                           object: nil)
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(sessionDidStopRunning(_:)),
                                           name: .AVCaptureSessionDidStopRunning,
                                           object: nil)
}

@objc
private func sessionDidStartRunning(_ notification: NSNotification) {
    self.startRecording()
}

@objc
private func sessionDidStopRunning(_ notification: NSNotification) {
    
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63028486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档