Swift: Put overlay on top of AVCaptureVideoPreviewLayer

With help of AVCaptureVideoPreviewLayer you can output video stream from camera on the phone’s screen, here’s how to do it without video or audio recording, just to capture the video and output on the main view

func startCapturing(view: SKView, background: CALayer, done: @escaping((_:CALayer)->())) {
    let device = getCamera()!
 
    do {
        captureSession.beginConfiguration()
 
        // Set up INPUTS
        try captureSession.addInput(AVCaptureDeviceInput(device: device))
 
        captureSession.sessionPreset = AVCaptureSessionPresetHigh
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
 
        if let previewLayer = previewLayer {
            // add background
            previewLayer.addSublayer(background)
 
            // init preview
            previewLayer.name = "camera"
            previewLayer.frame.size = view.bounds.size
            if IS_DEBUG {
                print("VideoService: size of previewLayer")
                print(previewLayer.frame.size)
            }
            previewLayer.position = CGPoint(
                x: view.frame.width/2, y: view.frame.height/2)
            view.layer.addSublayer(previewLayer)
            done(previewLayer)
        }
        captureSession.commitConfiguration()
        captureSession.startRunning()
 
        print("\n\nVideoService: camera configured")
    } catch {
        print("Error: start capturing failed")
    }
}
 
func getCaptureSessionBack() -> AVCaptureDeviceDiscoverySession {
    session = session ?? AVCaptureDeviceDiscoverySession(
        deviceTypes: [deviceTypeBackCamera],
        mediaType: AVMediaTypeVideo,
        position: position)
    return session!
}
 
func getCamera() -> AVCaptureDevice? {
    device = device ?? getCaptureSessionBack().devices.first
    return device
}

Let’s take a look at how to use it from let say main GameScene in SpriteKit, obviously after we have checked Camera permissions:

func addTo(scene: GameScene) {
    let view = scene.view!
    backgroundLayer.frame = view.frame
 
    scene.videoService.startCapturing(view: view, background: backgroundLayer, done: {layer in
        scene.videoLayer = layer
        layer.insertSublayer(self, above: layer)
    })
}

What is backgroundLayer? this is just a internal var backgroundLayer = CALayer()
And layer here is actually a AVCaptureVideoPreviewLayer
The idea here is that we take video preview layer and insert it as a sublayer into the backgroundLayer.
And here’s how we insert let say some image – contents = self.spinner.cgImage

Long story short we can use multiple CALayers together with layer.insertSublayer(self, above: layer) to make an overlay on the top of AVCaptureVideoPreviewLayer

Just to have an idea, here’s what I got – small app for example http://mikitamanko.com/ios/spinner/

This is it.

Social Share Toolbar