Попытка сделать экран, который позволяет пользователю записывать видео с 30-секундным таймером, а затем я хочу отправить его на сервер. Проблема в том, что метод делегата не вызывается (см. 2-ю часть кода).
То, что я сделал, это 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)")
}
}