how do i make a 3 second timer before taking a photo with avassetwriter in swift

main.swift
import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
    
    var capturing = false
    lazy var cameraSession: AVCaptureSession = AVCaptureSession()
    var videoDevice: AVCaptureDevice?
    var videoOutput: AVCaptureVideoDataOutput!
    let writer = try! AVAssetWriter(outputURL: makeUrl(), fileType: AVFileType.mp4)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup camera session
        cameraSession.beginConfiguration()
        cameraSession.sessionPreset = AVCaptureSessionPreset1280x720
        videoDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
        let videoInput = try! AVCaptureDeviceInput(device: videoDevice)
        cameraSession.addInput(videoInput)
        videoOutput = AVCaptureVideoDataOutput()
        videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sample buffer delegate", attributes: []))
        cameraSession.addOutput(videoOutput)
        cameraSession.commitConfiguration()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        cameraSession.startRunning()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        cameraSession.stopRunning()
        super.viewWillDisappear(animated)
    }
    
    // AVCaptureVideoDataOutputSampleBufferDelegate method
    func captureOutput(_ output: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        if capturing {
            writer.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
            writerInput.append(sampleBuffer)
        }
    }

    func startCapture() {
        capturing = true
        
        // Wait for 3 seconds
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) { [weak self] in
            guard let `self` = self else {
                return
            }
            
            // Start writing frames to file
            self.writer.add(self.writerInput)
            self.writer.startWriting()
            self.writer.startSession(atSourceTime: kCMTimeZero)
        }
    }
    
    func stopCapture(completion: () -> Void) {
        capturing = false
        
        writerInput.markAsFinished()
        writer.finishWriting { [weak self] in
            guard let `self` = self else {
                return
            }
            
            completion()
            self.writer.cancelWriting()
            self.writerInput = nil
        }
    }
    
    // Create url to save video
    static func makeUrl() -> URL {
        let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
        let fileName = dateFormatter.string(from: Date()) + ".mp4"
        let fileURL = URL(fileURLWithPath: documentDirectory).appendingPathComponent(fileName)
        
        return fileURL
    }
    
    lazy var writerInput: AVAssetWriterInput = {
        let settings = videoOutput.recommendedVideoSettingsForAssetWriter(writingTo: AVFileType.mp4)
        let input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: settings)
        input.expectsMediaDataInRealTime = true
        
        return input
    }()
}
3439 chars
95 lines

This code uses an AVCaptureSession to capture frames from the camera and an AVAssetWriter to write those frames to file. The startCapture method sets a capturing flag to true, waits for 3 seconds, and then starts writing frames to file. The stopCapture method sets the capturing flag to false, finishes writing frames to file, and calls a completion block. The captureOutput method is an AVCaptureVideoDataOutputSampleBufferDelegate method that gets called whenever a new frame is captured. It checks if capturing is true and if so, starts writing frames to file.

gistlibby LogSnag