如何在不使用预设的情况下在iOS上录制视频?

问题描述:

在iOS上录制视频的更简单方法是设置AVCaptureSession.sessionPreset如何在不使用预设的情况下在iOS上录制视频?

但这并不适用于我,因为我想控制像binning,稳定(电影,标准,或无)和ISO等参数。

我找到我想要的格式,并将其分配给activeFormat,但是当我试着开始录音,我得到一个错误:

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

这里是我的初始化代码:

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()被定义为:

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)") 
    } 
} 

最后的日志语句产生:

<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> 

这的确是我想要的格式,因此setFormatWithHighestIso()按预期工作。请参阅Apple reference


一些其他的事情我想:

  • 使用420V,而不是420F,通过改变== 875704422为=!
  • 取代在照片模式下启动相机,在视频模式下启动相机,然后通过删除AVCapturePhotoOutput并添加AVCaptureMovieFileOutput将其更改为视频模式。
  • 验证是否启用了AVCaptureConnection,并且是。
  • 验证该连接是活动的,但它不是:

    让康恩= output.connection(withMediaType:AVMediaTypeVideo)! 验证(conn.isActive)

我也尝试使用一些其他AVCaptureDeviceFormats,并且他们的工作:

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 
    } 
} 

它只能与不工作的最高ISO格式。这种格式有什么特别之处?

我是否需要手动创建AVCaptureConnection?但是已经有了联系;它只是不活跃。

这是运行iOS 10.3.3的iPhone 7 Plus。如何通过设置activeFormat而不使用会话以特定格式录制视频?

如果不是分配给activeFormat,而是使用sessionPreset,它会成功记录视频。


还有其他问题在谈论这个错误消息,但这不是他们的愚弄,因为我特别需要捕获视频而不使用预设。

+0

我想尝试一下,但没有7+ - 其他型号没有类似错误?你能添加错误信息吗?也许是一个可运行repro的链接? –

+0

我在问题中包含错误。我会尝试创建一个可运行的repro,但同时,你有什么设备?我会告诉你什么格式来尝试repro。 –

+0

我有一个6s - 将工作? –

解决方案原来是在将AVCaptureDevice添加到会话之前配置的。相反的:

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

你应该这样做:

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

当设备被添加到会话,创建并以某种方式配置的AVCaptureConnection。如果稍后更改设备的分辨率,则配置不再匹配,因此连接会被取消激活,并且视频不会被录制。