试图制作一个允许用户使用30秒计时器录制视频的屏幕,然后将其发送到服务器。问题在于未调用委托方法(请参见第二代码部分)。
我所做的是 PreviewView 作为UIView,时间和会话设置。即使当我检查 captureSession.isRecording 时,它也会显示 false
已更新:
ViewRepresentable
struct VideoRecordingView: UIViewRepresentable {
@Binding var timeLeft: Int
@Binding var onComplete: Bool
@Binding var recording: Bool
func makeUIView(context: UIViewRepresentableContext<VideoRecordingView>) -> PreviewView {
let recordingView = PreviewView()
recordingView.onComplete = {
self.onComplete = true
}
recordingView.onRecord = { timeLeft,totalShakes in
self.timeLeft = timeLeft
self.recording = true
}
recordingView.onReset = {
self.recording = false
self.timeLeft = 30
}
return recordingView
}
func updateUIView(_ uiViewController: PreviewView,context: UIViewRepresentableContext<VideoRecordingView>) {
}
}
查看
extension PreviewView: AVCaptureFileOutputRecordingDelegate{
func fileOutput(_ output: AVCaptureFileOutput,didFinishRecordingTo outputFileURL: URL,from connections: [AVCaptureConnection],error: Error?) {
print(outputFileURL.absoluteString) // Not called
}
}
class PreviewView: UIView {
private var captureSession: AVCaptureSession?
private var shakeCountDown: Timer?
let videoFileOutput = AVCaptureMovieFileOutput()
var recordingDelegate:AVCaptureFileOutputRecordingDelegate!
var recorded = 0
var secondsToReachgoal = 30
var onRecord: ((Int,Int)->())?
var onReset: (() -> ())?
var onComplete: (() -> ())?
init() {
super.init(frame: .zero)
var allowedaccess = false
let blocker = DispatchGroup()
blocker.enter()
AVCaptureDevice.requestaccess(for: .video) { flag in
allowedaccess = flag
blocker.leave()
}
blocker.wait()
if !allowedaccess {
print("!!! NO accESS TO CAMERA")
return
}
// setup session
let session = AVCaptureSession()
session.beginconfiguration()
let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera,for: .video,position: .front)
guard videoDevice != nil,let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!),session.canAddInput(videoDeviceInput) else {
print("!!! NO CAMERA DETECTED")
return
}
session.addInput(videoDeviceInput)
session.commitConfiguration()
self.captureSession = session
}
override class var layerClass: AnyClass {
AVCaptureVideoPreviewLayer.self
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
return layer as! AVCaptureVideoPreviewLayer
}
override func didmoveToSuperview() {
super.didmoveToSuperview()
recordingDelegate = self
startTimers()
startRecording()
if nil != self.superview {
self.videoPreviewLayer.session = self.captureSession
self.videoPreviewLayer.videoGravity = .resizeAspect
self.captureSession?.startRunning()
} else {
self.captureSession?.stopRunning()
}
}
private func onTimerFires(){
print("? RECORDING \(videoFileOutput.isRecording)")
secondsToReachgoal -= 1
recorded += 1
onRecord?(secondsToReachgoal,recorded)
if(secondsToReachgoal == 0){
stopRecording()
shakeCountDown?.invalidate()
shakeCountDown = nil
onComplete?()
videoFileOutput.stopRecording()
}
}
func startTimers(){
if shakeCountDown == nil {
shakeCountDown = Timer.scheduledTimer(withTimeInterval: 1,repeats: true) { [weak self] (timer) in
self?.onTimerFires()
}
}
}
func startRecording(){
captureSession?.addOutput(videoFileOutput)
let documentsURL = FileManager.default.urls(for: .documentDirectory,in: .userDomainmask)[0]
let filePath = documentsURL.appendingPathComponent("tempPZDC")
videoFileOutput.startRecording(to: filePath,recordingDelegate: recordingDelegate)
}
func stopRecording(){
videoFileOutput.stopRecording()
print("? RECORDING \(videoFileOutput.isRecording)")
}
}