如何在不使用预设的情况下在iOS上录制视频? [英] How do I record a video on iOS without using a preset?
问题描述
在iOS上录制视频的更简单方法是设置 AVCaptureSession.sessionPreset
。
The simpler way to record a video on iOS is by setting a AVCaptureSession.sessionPreset
.
但这对我不起作用,因为我想控制合并等参数,稳定(电影,标准或无)和ISO。
But that doesn't work for me since I want to control parameters like binning, stabilization (cinematic, standard, or none) and ISO.
我找到了想要的格式并将其分配给 activeFormat
,但是当我尝试开始记录时,出现错误:
I find the format I want and assign it to activeFormat
, but when I try to start recording, I get an error:
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)")
}
}
最后一个日志语句产生:
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>
这确实是我想要的格式,所以 setFormatWithHighestIso()
工作正常。请参阅Apple 参考。
This is indeed the format I want, so setFormatWithHighestIso()
is working as expected. See the Apple reference.
我尝试过的其他操作:
- 通过将== 875704422更改为!=,使用420v而不是420f。
- 而不是在照片模式,以视频模式启动它,然后通过删除AVCapturePhotoOutput并添加AVCaptureMovieFileOutput将其更改为视频模式。
- 验证是否已启用AVCaptureConnection。
-
验证连接处于活动状态,但不是:
- Using 420v instead of 420f, by changing the == 875704422 to !=.
- Instead of starting the camera in photo mode, starting it in video mode, and then changing it to video mode by removing the AVCapturePhotoOutput and adding the AVCaptureMovieFileOutput.
- Verifying that the AVCaptureConnection is enabled, and it is.
Verifying that the connection is active, but it's not:
let conn = output.connection(withMediaType:AVMediaTypeVideo)!
verify(conn.isActive)
let conn = output.connection(withMediaType: AVMediaTypeVideo)! verify(conn.isActive)
我也尝试使用其他一些 AVCaptureDeviceFormats
,并且它们起作用:
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
}
}
仅具有最高ISO的格式不起作用。这种格式有什么特别之处?
It's only the format with the highest ISO that doesn't work. What's special about this format?
我需要手动创建AVCaptureConnection吗?但是已经有了联系;
Do I need to manually create an AVCaptureConnection? But there's already a connection; it's just not active.
这是在运行iOS 10.3.3的iPhone 7 Plus上。如何通过设置activeFormat而不使用会话来以特定格式录制视频?
This is on the iPhone 7 Plus running iOS 10.3.3. How do I record video in a specific format by setting the activeFormat without using a session?
如果我不是使用分配给activeFormat的会话,而是使用sessionPreset录制了一个视频成功。
If, instead of assigning to activeFormat, I use a sessionPreset, it does record a video successfully.
还有其他关于此错误消息的问题,但这并不是我的错
There are other questions talking of this error message, but this isn't a dupe of them since I specifically need to capture video without using a preset.
推荐答案
该解决方案原来是在将AVCaptureDevice添加到会话之前对其进行配置的。而不是:
The solution turned out to be configuring the AVCaptureDevice before adding it to a session. Instead of:
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。如果稍后更改设备的分辨率,则配置将不再匹配,因此连接将被停用,并且视频也将无法录制。
When the device is added to the session, an AVCaptureConnection is created and configured in a certain way. If you change the device's resolution later, the configuration no longer matches, so the connection gets deactivated, and the video won't record.
这篇关于如何在不使用预设的情况下在iOS上录制视频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!