How to record video on iOS without using a preset?

An easier way to record video on iOS is to set AVCaptureSession.sessionPreset .

But this does not work for me, since I want to control parameters such as binning, stabilization (cinematic, standard or none) and ISO.

I find the format I want and assign it activeFormat , but when I try to start recording, I get an error message:

 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] No active/enabled connections' 

Here is my initialization code:

 let device = AVCaptureDevice.defaultDevice( withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back)! let session = AVCaptureSession() session.addInput(try! AVCaptureDeviceInput(device: device)) output = AVCaptureMovieFileOutput() session.addOutput(output) device.setFormatWithHighestIso() session.startRunning() 

setFormatWithHighestIso() is defined as:

 extension AVCaptureDevice { var goodVideoFormats: [AVCaptureDeviceFormat] { return (formats as! [AVCaptureDeviceFormat]) .filter { CMFormatDescriptionGetMediaSubType($0.formatDescription) != 875704422 } // 420f .filter { $0.autoFocusSystem == .phaseDetection } } func setFormatWithHighestIso() { let format = goodVideoFormats .filter { $0.maxISO > 1759 } .filter { $0.height < 1937 } .first! try! lockForConfiguration() defer { unlockForConfiguration() } activeFormat = format NSLog("\(format)") } } 

The last log statement produces:

 <AVCaptureDeviceFormat: 0x1702027d0 'vide'/'420f' 2592x1936, { 3- 30 fps}, HRSI:4032x3024, fov:58.986, max zoom:189.00 (upscales @1.56), AF System:2, ISO:22.0-1760.0, SS:0.000005-0.333333, supports wide color> 

This is really the format I want, so setFormatWithHighestIso() works as expected. See Apple reference .


Some other things I've tried:

  • Using 420v instead of 420f, changing == 875704422 to! =.
  • Instead of launching the camera in photo mode, start it in video mode, and then change it in video mode by removing AVCapturePhotoOutput and adding AVCaptureMovieFileOutput.
  • Verifying that AVCaptureConnection is enabled, and that.
  • Checking the connection activity, but it is not:

    let conn = output.connection (withMediaType: AVMediaTypeVideo)! check (conn.isActive)

I also tried using some other AVCaptureDeviceFormats , and they work:

 extension AVCaptureDevice { func setFormatWithCinematicVS() { let format = goodVideoFormats .filter { $0.isVideoStabilizationModeSupported(.cinematic) } .filter { $0.height == 720 } .first! try! lockForConfiguration() defer { unlockForConfiguration() } activeFormat = format } func setFormatWithStandardVS() { let format = goodVideoFormats .filter { $0.isVideoStabilizationModeSupported(.standard) } .filter { $0.height == 540 } .first! try! lockForConfiguration() defer { unlockForConfiguration() } activeFormat = format } } 

This is only the highest ISO format that does not work. What is special about this format?

Do I need to manually create an AVCaptureConnection? But there is already a connection; it is simply inactive.

This is on the iPhone 7 Plus running iOS 10.3.3. How to record video in a specific format by setting the active format without using a session?

If instead of assigning activeFormat I use sessionPreset, it successfully records the video.


There are other issues related to this error message, but this is not a hoax, as I specifically have to shoot video without using a preset.

+2
ios avcapturesession avcapturedevice avcapture
source share
1 answer

The solution turned out to be the need to configure AVCaptureDevice before adding it to the session. Instead:

 session.addInput(try! AVCaptureDeviceInput(device: device)) output = AVCaptureMovieFileOutput() session.addOutput(output) device.setFormatWithHighestIso() 

You should:

 device.setFormatWithHighestIso() // Do this first! session.addInput(try! AVCaptureDeviceInput(device: device)) output = AVCaptureMovieFileOutput() session.addOutput(output) 

When a device is added to a session, AVCaptureConnection is created and configured in a specific way. If you subsequently change the resolution of the device, the configuration will no longer match, so the connection will be deactivated and the video will not be recorded.

0
source share

All Articles