8

Today i am coding for Mac first time. What I am trying to do is access the default camera and show a preview. 2nd step i will record or take a snap if i need. For the 1st step i have written the following code

import Cocoa
import AVFoundation
class ViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        var session:AVCaptureSession = AVCaptureSession()
        session.sessionPreset = AVCaptureSessionPresetLow
        var device:AVCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        //Preview
        var previewLayer:AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
        var myView:NSView = self.view
        previewLayer.frame = myView.bounds
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        self.view.layer?.addSublayer(previewLayer)
        session.startRunning()
    }
    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

I don't see this code is turning on my laptop default camera or displaying anything on the view. What am i doing wrong here? Any direction or any example i can look for even if its in Obj-C would be really helpful. TIA.

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
KD.
  • 2,015
  • 3
  • 28
  • 59
  • 1
    Sandbox issue? Did you look in the console log? – qwerty_so Feb 28 '15 at 15:45
  • Sorry whats a sandbox issue? No error on console and no error thrown even while debugging. Running without a dev certificate as don't have a mac dev certificate yet – KD. Feb 28 '15 at 15:47
  • Mac apps may run in a sandbox (or need if you place them on the AppStore). So you can forget that... – qwerty_so Feb 28 '15 at 15:56
  • @KD. did you get anywhere with this? – colincameron Jan 16 '18 at 11:19
  • Here is my working gist https://gist.github.com/knoguchi/9c7cd044f5cfcea112e0aa634d9f4e04 – Kenji Noguchi Jan 01 '19 at 03:12
  • I found none of the answers below useful, but using the code form https://github.com/fbukevin/AccessCamera/blob/master/AccessCamera/ViewController.swift, I was able to get up and running. – Peter Aug 14 '19 at 00:49

4 Answers4

4

In your code the

self.view.layer?.addSublayer(previewLayer)

will not be executed since self.view.layer is nil so that won't be executed.

Alas, this does not seem to be only issue since even when adding a layer the camera does not start working. You will likely have to dig into this:

https://developer.apple.com/library/mac/samplecode/AVRecorder/Introduction/Intro.html

qwerty_so
  • 35,448
  • 8
  • 62
  • 86
4

Working code in swift 5.

import Cocoa
import AVFoundation

class SomwViewController: NSViewController {
    @IBOutlet private var cameraView: NSView?
    let session: AVCaptureSession = AVCaptureSession()

    override func viewDidLoad() {
        super.viewDidLoad()
        cameraView?.wantsLayer = true
        cameraView?.layer?.backgroundColor = NSColor.black.cgColor
        session.sessionPreset = AVCaptureSession.Preset.low
        let input: AVCaptureInput = try! AVCaptureDeviceInput(device: AVCaptureDevice.default(for: .video)!)
        session.addInput(input)
        let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
        previewLayer.frame = cameraView!.bounds
        previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

        cameraView?.layer?.addSublayer(previewLayer)
    }

    override func viewDidAppear() {
        session.startRunning()
    }

    override func viewDidDisappear() {
        session.stopRunning()
    }
}

You should definitely not use force unwraps, it's just an example.

SUMIT NIHALANI
  • 387
  • 1
  • 10
3

Be sure to check that your view has a Core Animation Layer in IB:

enter image description here

Rick
  • 3,298
  • 3
  • 29
  • 47
  • It was helpful. Thank you, Rick! It's so sad that without checking it, code just runs without exceptions but does nothing. – rudyryk Oct 13 '16 at 18:44
  • Actually, I find that quite nice. In Swift, you opt-in to that behavior with '?'. In the case of IB, well, you need to tell it what you want. It'd be like forgetting to add a view and then being upset that a view you wanted didn't appear. – Rick Oct 13 '16 at 21:58
-1

if anyone still looking to launch webcam in Mac OS X using swift 3

here is the code

@IBOutlet var previewCam: PreviewCam!
override func viewDidLoad()
{
    super.viewDidLoad()
    view.wantsLayer = true
    previewCam.wantsLayer = true
    let session:AVCaptureSession = AVCaptureSession()
    session.sessionPreset = AVCaptureSessionPresetLow
    let device:AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
    print("device found = ",device)

    let device_input : AVCaptureDeviceInput = try! AVCaptureDeviceInput(device: device)


    let previewLayer:AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)

    previewLayer.frame = previewCam.bounds
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    self.previewCam.layer?.addSublayer(previewLayer)
    if session.canAddInput(device_input)
    {
        session.addInput(device_input)
    }
    session.startRunning()
}

for those who asked about preview cam

#import "PreviewCam.h"

@implementation PreviewCam

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    // Drawing code here.
    CGContextRef context = [[NSGraphicsContext currentContext]graphicsPort];
    CGContextSetRGBFillColor(context, 0, 0, 0, 0.75);
    CGContextFillRect(context, NSRectToCGRect(dirtyRect));
    self.layer.borderColor = [[NSColor whiteColor]CGColor];
    self.layer.borderWidth = 2.0f;
}
rolling Ztoned
  • 47
  • 2
  • 11