How to switch cameras during recording [duplicate] - ios

Using this tutorial here: http://www.musicalgeometry.com/?p=1297 I have created a custom overlay and image capture with AVCaptureSession.
I am attempting to allow the user to switch between the front and back camera. Here is my code in CaptureSessionManager to switch cameras:
- (void)addVideoInputFrontCamera:(BOOL)front {
NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *frontCamera;
AVCaptureDevice *backCamera;
for (AVCaptureDevice *device in devices) {
//NSLog(#"Device name: %#", [device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionBack) {
//NSLog(#"Device position : back");
backCamera = device;
}
else {
//NSLog(#"Device position : front");
frontCamera = device;
}
}
}
NSError *error = nil;
if (front) {
AVCaptureDeviceInput *frontFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
if (!error) {
if ([[self captureSession] canAddInput:frontFacingCameraDeviceInput]) {
[[self captureSession] addInput:frontFacingCameraDeviceInput];
} else {
NSLog(#"Couldn't add front facing video input");
}
}
} else {
AVCaptureDeviceInput *backFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
if (!error) {
if ([[self captureSession] canAddInput:backFacingCameraDeviceInput]) {
[[self captureSession] addInput:backFacingCameraDeviceInput];
} else {
NSLog(#"Couldn't add back facing video input");
}
}
}
}
Now in my custom overlay controller I initialize everything like so in viewDidLoad:
[self setCaptureManager:[[CaptureSessionManager alloc] init]];
[[self captureManager] addVideoInputFrontCamera:NO]; // set to YES for Front Camera, No for Back camera
[[self captureManager] addStillImageOutput];
[[self captureManager] addVideoPreviewLayer];
CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];
[[_captureManager captureSession] startRunning];
The switch camera button is connected to a method called switchCamera. I have tried this:
- (void)switchCameraView:(id)sender {
[[self captureManager] addVideoInputFrontCamera:YES]; // set to YES for Front Camera, No for Back camera
}
When calling this, I get the error NSLog from the CaptureSessionManager and I cannot figure out why. In viewDidLoad, if I set the fontCamera to YES, it shows the front camera but cannot switch to back, and vice versa.
Any ideas on how to get it to switch properly?

You first need to remove the existing AVCameraInput from the AVCaptureSession and then add a new AVCameraInput to the AVCaptureSession. The following works for me (under ARC):
-(IBAction)switchCameraTapped:(id)sender
{
//Change camera source
if(_captureSession)
{
//Indicate that some changes will be made to the session
[_captureSession beginConfiguration];
//Remove existing input
AVCaptureInput* currentCameraInput = [_captureSession.inputs objectAtIndex:0];
[_captureSession removeInput:currentCameraInput];
//Get new input
AVCaptureDevice *newCamera = nil;
if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack)
{
newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
}
else
{
newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
}
//Add input to session
NSError *err = nil;
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&err];
if(!newVideoInput || err)
{
NSLog(#"Error creating capture device input: %#", err.localizedDescription);
}
else
{
[_captureSession addInput:newVideoInput];
}
//Commit all the configuration changes at once
[_captureSession commitConfiguration];
}
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices)
{
if ([device position] == position) return device;
}
return nil;
}

Swift 4/5
#IBAction func switchCameraTapped(sender: Any) {
//Change camera source
if let session = captureSession {
//Remove existing input
guard let currentCameraInput: AVCaptureInput = session.inputs.first else {
return
}
//Indicate that some changes will be made to the session
session.beginConfiguration()
session.removeInput(currentCameraInput)
//Get new input
var newCamera: AVCaptureDevice! = nil
if let input = currentCameraInput as? AVCaptureDeviceInput {
if (input.device.position == .back) {
newCamera = cameraWithPosition(position: .front)
} else {
newCamera = cameraWithPosition(position: .back)
}
}
//Add input to session
var err: NSError?
var newVideoInput: AVCaptureDeviceInput!
do {
newVideoInput = try AVCaptureDeviceInput(device: newCamera)
} catch let err1 as NSError {
err = err1
newVideoInput = nil
}
if newVideoInput == nil || err != nil {
print("Error creating capture device input: \(err?.localizedDescription)")
} else {
session.addInput(newVideoInput)
}
//Commit all the configuration changes at once
session.commitConfiguration()
}
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
for device in discoverySession.devices {
if device.position == position {
return device
}
}
return nil
}
Swift 3 Edit (Combined with François-Julien Alcaraz answer):
#IBAction func switchCameraTapped(sender: Any) {
//Change camera source
if let session = captureSession {
//Indicate that some changes will be made to the session
session.beginConfiguration()
//Remove existing input
guard let currentCameraInput: AVCaptureInput = session.inputs.first as? AVCaptureInput else {
return
}
session.removeInput(currentCameraInput)
//Get new input
var newCamera: AVCaptureDevice! = nil
if let input = currentCameraInput as? AVCaptureDeviceInput {
if (input.device.position == .back) {
newCamera = cameraWithPosition(position: .front)
} else {
newCamera = cameraWithPosition(position: .back)
}
}
//Add input to session
var err: NSError?
var newVideoInput: AVCaptureDeviceInput!
do {
newVideoInput = try AVCaptureDeviceInput(device: newCamera)
} catch let err1 as NSError {
err = err1
newVideoInput = nil
}
if newVideoInput == nil || err != nil {
print("Error creating capture device input: \(err?.localizedDescription)")
} else {
session.addInput(newVideoInput)
}
//Commit all the configuration changes at once
session.commitConfiguration()
}
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice? {
if let discoverySession = AVCaptureDeviceDiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: .unspecified) {
for device in discoverySession.devices {
if device.position == position {
return device
}
}
}
return nil
}
Swift version to #NES_4Life's answer:
#IBAction func switchCameraTapped(sender: AnyObject) {
//Change camera source
if let session = captureSession {
//Indicate that some changes will be made to the session
session.beginConfiguration()
//Remove existing input
let currentCameraInput:AVCaptureInput = session.inputs.first as! AVCaptureInput
session.removeInput(currentCameraInput)
//Get new input
var newCamera:AVCaptureDevice! = nil
if let input = currentCameraInput as? AVCaptureDeviceInput {
if (input.device.position == .Back)
{
newCamera = cameraWithPosition(.Front)
}
else
{
newCamera = cameraWithPosition(.Back)
}
}
//Add input to session
var err: NSError?
var newVideoInput: AVCaptureDeviceInput!
do {
newVideoInput = try AVCaptureDeviceInput(device: newCamera)
} catch let err1 as NSError {
err = err1
newVideoInput = nil
}
if(newVideoInput == nil || err != nil)
{
print("Error creating capture device input: \(err!.localizedDescription)")
}
else
{
session.addInput(newVideoInput)
}
//Commit all the configuration changes at once
session.commitConfiguration()
}
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice?
{
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
for device in devices {
let device = device as! AVCaptureDevice
if device.position == position {
return device
}
}
return nil
}

Based on previous answers I made my own version with some validations and one specific change, the current camera input might not be the first object of the capture session's inputs, so I changed this:
//Remove existing input
AVCaptureInput* currentCameraInput = [self.captureSession.inputs objectAtIndex:0];
[self.captureSession removeInput:currentCameraInput];
To this (removing all video type inputs):
for (AVCaptureDeviceInput *input in self.captureSession.inputs) {
if ([input.device hasMediaType:AVMediaTypeVideo]) {
[self.captureSession removeInput:input];
break;
}
}
Here's the entire code:
if (!self.captureSession) return;
[self.captureSession beginConfiguration];
AVCaptureDeviceInput *currentCameraInput;
// Remove current (video) input
for (AVCaptureDeviceInput *input in self.captureSession.inputs) {
if ([input.device hasMediaType:AVMediaTypeVideo]) {
[self.captureSession removeInput:input];
currentCameraInput = input;
break;
}
}
if (!currentCameraInput) return;
// Switch device position
AVCaptureDevicePosition captureDevicePosition = AVCaptureDevicePositionUnspecified;
if (currentCameraInput.device.position == AVCaptureDevicePositionBack) {
captureDevicePosition = AVCaptureDevicePositionFront;
} else {
captureDevicePosition = AVCaptureDevicePositionBack;
}
// Select new camera
AVCaptureDevice *newCamera;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *captureDevice in devices) {
if (captureDevice.position == captureDevicePosition) {
newCamera = captureDevice;
}
}
if (!newCamera) return;
// Add new camera input
NSError *error;
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&error];
if (!error && [self.captureSession canAddInput:newVideoInput]) {
[self.captureSession addInput:newVideoInput];
}
[self.captureSession commitConfiguration];

Swift 3
func switchCamera() {
session?.beginConfiguration()
let currentInput = session?.inputs.first as? AVCaptureDeviceInput
session?.removeInput(currentInput)
let newCameraDevice = currentInput?.device.position == .back ? getCamera(with: .front) : getCamera(with: .back)
let newVideoInput = try? AVCaptureDeviceInput(device: newCameraDevice)
session?.addInput(newVideoInput)
session?.commitConfiguration()
}
// MARK: - Private
extension CameraService {
func getCamera(with position: AVCaptureDevicePosition) -> AVCaptureDevice? {
guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else {
return nil
}
return devices.filter {
$0.position == position
}.first
}
}
Swift 4
You can check full implementation in this gist

Here is an updated version of chengsam's code that includes the fix for 'Multiple audio/video AVCaptureInputs are not currently supported'.
func switchCameraTapped() {
//Change camera source
//Indicate that some changes will be made to the session
session.beginConfiguration()
//Remove existing input
guard let currentCameraInput: AVCaptureInput = session.inputs.first else {
return
}
//Get new input
var newCamera: AVCaptureDevice! = nil
if let input = currentCameraInput as? AVCaptureDeviceInput {
if (input.device.position == .back) {
newCamera = cameraWithPosition(position: .front)
} else {
newCamera = cameraWithPosition(position: .back)
}
}
//Add input to session
var err: NSError?
var newVideoInput: AVCaptureDeviceInput!
do {
newVideoInput = try AVCaptureDeviceInput(device: newCamera)
} catch let err1 as NSError {
err = err1
newVideoInput = nil
}
if let inputs = session.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
session.removeInput(input)
}
}
if newVideoInput == nil || err != nil {
print("Error creating capture device input: \(err?.localizedDescription)")
} else {
session.addInput(newVideoInput)
}
//Commit all the configuration changes at once
session.commitConfiguration()
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
for device in discoverySession.devices {
if device.position == position {
return device
}
}
return nil
}

Swift 3 version of cameraWithPosition without deprecated warning :
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(_ position: AVCaptureDevicePosition) -> AVCaptureDevice?
{
if let deviceDescoverySession = AVCaptureDeviceDiscoverySession.init(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera],
mediaType: AVMediaTypeVideo,
position: AVCaptureDevicePosition.unspecified) {
for device in deviceDescoverySession.devices {
if device.position == position {
return device
}
}
}
return nil
}
If you want, you can also get the new devicesTypes from iPhone 7+ (dual camera) by changing the deviceTypes array.
Here's a good read : https://forums.developer.apple.com/thread/63347

Related

Camera flash is not working from uiimageviewcontroller ios

Does not blink any flash light -
-(void)_flashToggle
{
if (! [UIImagePickerController isFlashAvailableForCameraDevice:UIImagePickerControllerCameraDeviceRear ])
return;
if (PickerController.cameraFlashMode == UIImagePickerControllerCameraFlashModeOff)
PickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeOn;
else
PickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
}
You can easily change the device torch mode by accessing it using AVFoundation framework like:
Swift 3.0
func toggleTorchMode() {
if let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo), device.hasTorch {
let isTorchSupported = device.isTorchModeSupported(mode)
let isTourchAvailable = device.isTorchAvailable
if isTorchSupported && isTourchAvailable {
do {
try device.lockForConfiguration()
if device.torchMode == AVCaptureTorchMode.on {
device.torchMode = AVCaptureTorchMode.off
}
else {
device.torchMode = AVCaptureTorchMode.on
}
device.unlockForConfiguration()
} catch {
Globals.printlnDebug("Error in setting the torch mode")
}
}
else if mode == AVCaptureTorchMode.on{
Globals.showErrorMessage("Torch not available", inViewController: self)
}
}
}
Objective-C
-(void)toggleTorchMode
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ((device) && (device.hasTorch) && (device.isTorchAvailable)) {
[device lockForConfiguration:nil];
if (device.torchMode == AVCaptureTorchModeOn) {
device.torchMode = AVCaptureTorchModeOff;
}
else {
device.torchMode = AVCaptureTorchModeOn;
}
}
else {
//ERROR: Device doesn't have tourch
}
}

Setting AVCapturedevice.flashmode for front Camera throws "error while capturing still image" when taking still image

When I set the flashmode for my front camera and then call
let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: process)
I get the following error message:
error while capturing still image: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x12eeb7200 {Error Domain=NSOSStatusErrorDomain Code=-16800 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-16800), NSLocalizedDescription=The operation could not be completed}
If I don't set the camera's flashMode and then call:
let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: process)
The front camera takes a picture and doesn't throw the error.
Currently, this is how I set up my camera:
func getCameraStreamLayer() -> CALayer? {
captureSession = AVCaptureSession()
captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
currentCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput!.outputSettings = [ AVVideoCodecKey: AVVideoCodecJPEG ]
if let input = try? AVCaptureDeviceInput(device: currentCamera) as AVCaptureDeviceInput{
if captureSession!.canAddInput(input) && captureSession!.canAddOutput(stillImageOutput) {
captureSession!.addInput(input)
captureSession!.addOutput(stillImageOutput)
}
}
return AVCaptureVideoPreviewLayer(session: captureSession)
}
func toggleFlash() {
flash = !flash
if flash {
for case let (device as AVCaptureDevice) in AVCaptureDevice.devices() {
if device.hasFlash && device.flashAvailable {
if device.isFlashModeSupported(.On) {
do {
try device.lockForConfiguration()
device.flashMode = .On
device.unlockForConfiguration()
} catch {
print("Something went wrong")
}
}
}
}
}else {//turn off flash
}
}
func photograph(process: (CMSampleBuffer!,NSError!)->()) {
let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: process)
}
func flipCamera() {
guard let session = captureSession where session.running == true else {
return
}
session.beginConfiguration()
let currentCameraInput = session.inputs[0] as! AVCaptureDeviceInput
session.removeInput(currentCameraInput)
let newCamera = {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
for case let device as AVCaptureDevice in devices {
if(device.position == .Front && currentCameraInput.device.position == .Back){
return device
}
if(device.position == .Back && currentCameraInput.device.position == .Front){
return device
}
}
return nil
}() as AVCaptureDevice?
currentCamera = newCamera!
if let newVideoInput = try? AVCaptureDeviceInput(device: newCamera) {
captureSession?.addInput(newVideoInput)
}
captureSession?.commitConfiguration()
}
I'm not sure what I should do. I've tried to create a new capture session and then lock and then set the flashMode for the camera. I still get the same error.

AVFoundation Camera Check and Flip Variable

I created a custom camera tool. Now, I am trying to handle checking existence of cameras however, I only have Simulator (no camera) and iphone (both cameras). I handled no camera but I couldn't understand how it works for one camera, so I also couldn't figure out how to help the user flip the camera
Currently I am using following external library using dojo custom camera
Position .Back and .Front works, and I handled no camera, but I couldn't figure out how to
handle checks for 1 camera
assign a variable for the control of Back & Front cameras depending on their existence (So I can create a uibutton in the VC and control flipping of camera back and front).
// I call addVideoInput() while initializing
func addVideoInput() {
if let device: AVCaptureDevice = self.deviceWithMediaTypeWithPosition(AVMediaTypeVideo, position: AVCaptureDevicePosition.Front) {
do {
let input = try AVCaptureDeviceInput(device: device)
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error)
}
}
}
func deviceWithMediaTypeWithPosition(mediaType: NSString, position: AVCaptureDevicePosition) -> AVCaptureDevice? {
let devices: NSArray = AVCaptureDevice.devicesWithMediaType(mediaType as String)
if devices.count != 0 {
if var captureDevice: AVCaptureDevice = devices.firstObject as? AVCaptureDevice {
for device in devices {
let d = device as! AVCaptureDevice
if d.position == position {
captureDevice = d
break;
}
}
print(captureDevice)
return captureDevice
}
}
print("doesnt have any camera")
return nil
}
You need to remove the object and create new object with use of few values and boolean uses.
Here I post the code for the when create the position of the camera AVCaptureDevicePosition.
In the top of the class add enum.
enum CameraType {
case Front
case Back
}
Initialise the variable.
var cameraCheck = CameraType.Back
Just change the following function.
func addVideoInput() {
if cameraCheck == CameraType.Front {
cameraCheck = CameraType.Back
let device: AVCaptureDevice = self.deviceWithMediaTypeWithPosition(AVMediaTypeVideo, position: AVCaptureDevicePosition.Front)
do {
let input = try AVCaptureDeviceInput(device: device)
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error)
}
}else{
cameraCheck = CameraType.Front
let device: AVCaptureDevice = self.deviceWithMediaTypeWithPosition(AVMediaTypeVideo, position: AVCaptureDevicePosition.Back)
do {
let input = try AVCaptureDeviceInput(device: device)
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error)
}
}
}
Create one button into your storyboard.
Now into your viewcontroller create one #IBAction function.
#IBAction func changeCamera(){
self.camera = nil
self.initializeCamera()
self.establishVideoPreviewArea()
if isBackCamera == true {
isBackCamera = false
self.camera?.cameraCheck = CameraType.Front
}else{
isBackCamera = true
self.camera?.cameraCheck = CameraType.Back
}
}
That's it your goal achieve.
Also you can download the source code from here.
You can use a boolean variable isUsingFrontCamera, for the first time when the camera view loads,
Set,
isUsingFrontCamera = false;
Then on clicking on the camera switch button,
-(IBAction)switchCameras:(id)sender {
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera)
desiredPosition = AVCaptureDevicePositionBack;
else
desiredPosition = AVCaptureDevicePositionFront;
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[captureVideoPreviewLayer session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[captureVideoPreviewLayer session] inputs]) {
[[captureVideoPreviewLayer session] removeInput:oldInput];
}
[[captureVideoPreviewLayer session] addInput:input];
[[captureVideoPreviewLayer session] commitConfiguration];
break;
}
}
isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
}
Where captureVideoPreviewLayer is the,
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer
Also, you can get the count of your camera using
[[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count]
Then show and hide button accordingly
Best to keep an enum IMO.
private enum CameraPosition {
case Front, Back
}
Then when you press the button have
var currentState: CameraPostition
switch to the other camera position.
Then on the didSet of currentState config the camera
var currentState: CameraPostition {
didSet {
configCamera(state: currentState)
}
}
EDIT: After some more information provided.
If you change
func addVideoInput() {
let device: AVCaptureDevice = self.deviceWithMediaTypeWithPosition(AVMediaTypeVideo, position: AVCaptureDevicePosition.Back)
do {
let input = try AVCaptureDeviceInput(device: device)
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error)
}
}
To
func addVideoInput(position: AVCaptureDevicePosition) {
let device: AVCaptureDevice = self.deviceWithMediaTypeWithPosition(AVMediaTypeVideo, position: position)
do {
let input = try AVCaptureDeviceInput(device: device)
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error)
}
}
Then when your "CurrentState" changes on the didSet of currentState you can just call the function.
func configCamera(state: CameraState) {
switch state{
case .Back:
addVideoInput(.Back)
case .Front
addVideoInput(.Front)
}
}

EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT,subcode=0xe7ffdefe)

Hi I am getting this error.
It should be because of this code (it should switch between front and back camera in my custom camera). I am able to take a picture and everything works fine except this code...
#IBAction func switchCamera(sender: UIButton) {
var session:AVCaptureSession!
let currentCameraInput: AVCaptureInput = session.inputs[0] as! AVCaptureInput
session.removeInput(currentCameraInput)
do {
let newCamera: AVCaptureDevice?
if(captureDevice!.position == AVCaptureDevicePosition.Back){
print("Setting new camera with Front")
newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Front)
} else {
print("Setting new camera with Back")
newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Back)
}
let error = NSError?()
let newVideoInput = try AVCaptureDeviceInput(device: newCamera)
if (error == nil && captureSession?.canAddInput(newVideoInput) != nil) {
session.addInput(newVideoInput)
} else {
print("Error creating capture device input")
}
session.commitConfiguration()
captureDevice! = newCamera!
} catch let error as NSError {
// Handle any errors
print(error)
}
}
Thanks.

AVCaptureMovieFileOutput record audio only for the first video

I'm developing an application using swift that record video for a precise duration. That's 7 sec in this example.
All work's great for the first record, but the successive record doesn't contain audio but only video.
I read something about changing the movieFragmentInterval of the AVCaptureMovieFileOutput instance, I try but nothing change.
func setup(){
self.session = AVCaptureSession()
self.session.sessionPreset = AVCaptureSessionPresetHigh
// INPUT
var devices : Array<AVCaptureDevice> = AVCaptureDevice.devices() as Array<AVCaptureDevice>
var camera:AVCaptureDevice!
var microphone:AVCaptureDevice!
for device in devices{
println("Device name: \(device)")
if device.hasTorch && device.isTorchModeSupported(AVCaptureTorchMode.On){
self.torch = device
}
if device.hasMediaType(AVMediaTypeAudio){
microphone = device
}
if device.hasMediaType(AVMediaTypeVideo){
if device.position == .Back{
println("Device position: back.")
camera = device
} } }
var error:NSErrorPointer = nil
// audio
if (microphone != nil){
var audioInput = AVCaptureDeviceInput(device: microphone, error: error)
if error == nil{
// if !error{
if self.session.canAddInput(audioInput){
self.session.addInput(audioInput)
} } }
// video input
if (camera != nil){
var VideoInput = AVCaptureDeviceInput(device: camera, error: error)
// if !error{
if error == nil{
if self.session.canAddInput(VideoInput){
self.session.addInput(VideoInput)
} } }
self.output = AVCaptureMovieFileOutput()
var preferredTimeScale:Int32 = 30
var totalSeconds:Int64 = Int64(Int(7) * Int(preferredTimeScale)) // after 7 sec video recording stop automatically
var maxDuration:CMTime = CMTimeMake(totalSeconds, preferredTimeScale)
self.output.maxRecordedDuration = maxDuration
self.output.minFreeDiskSpaceLimit = 1024 * 1024
if session.canAddOutput(self.output){
session.addOutput(self.output)
}
self.connection = self.output.connectionWithMediaType(AVMediaTypeVideo)
if self.connection.supportsVideoStabilization == true{
println("video stabilization avaible")
self.connection.enablesVideoStabilizationWhenAvailable = true
}
self.connection.videoOrientation = .LandscapeRight
self.session.startRunning()
}
func startRecording(){
self.output.startRecordingToOutputFileURL(self.tempPathURL, recordingDelegate: self)
}
func stopRecording(){
self.output.stopRecording()
}
func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!){
println("Finish recording")
var success:Bool = false
if error != 0 && error != nil{
println("error")
let value: AnyObject? = error.userInfo?[AVErrorRecordingSuccessfullyFinishedKey]
if value == nil{
success = true
}else{
success = false
}
}
if success == true{
stopRecording()
}
}

Resources