【问题标题】:How do I record a video on iOS without using a preset?如何在不使用预设的情况下在 iOS 上录制视频?
【发布时间】:2018-02-19 23:21:24
【问题描述】:

在 iOS 上录制视频的更简单方法是设置 AVCaptureSession.sessionPreset

但这对我不起作用,因为我想控制分档、稳定(电影、标准或无)和 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() 正在按预期工作。见苹果reference


我尝试过的其他一些事情:

  • 使用 420v 而不是 420f,将 == 875704422 更改为 !=。
  • 不是以照片模式启动相机,而是以视频模式启动,然后通过删除 AVCapturePhotoOutput 并添加 AVCaptureMovieFileOutput 将其更改为视频模式。
  • 验证 AVCaptureConnection 是否已启用。
  • 验证连接是否处于活动状态:

    让 conn = 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,它确实会成功录制视频。


还有其他关于此错误消息的问题,但这不是他们的骗局,因为我特别需要在不使用预设的情况下捕获视频。

【问题讨论】:

  • 我想试试这个,但没有 7+ - 其他型号没有类似的错误?你能添加错误信息吗?也许还有一个可运行再现的链接?
  • 我在问题中包含了错误。我会尝试创建一个可运行的复制品,但与此同时,你有什么设备?我会告诉你尝试复制的格式。
  • 我有一个 6s - 可以吗?
  • 对于 6s,在我的代码中,请将 maxISO > 1759 更改为 1839,您应该会看到问题。

标签: ios avcapturesession avcapturedevice avcapture avcapturemoviefileoutput


【解决方案1】:

解决方案是在将 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。如果您稍后更改设备的分辨率,则配置不再匹配,因此连接将被停用,视频将无法录制。

【讨论】:

    猜你喜欢
    • 2014-11-22
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多