如何使用 AVCaptureDeviceFormat 从 iPhone 录制延时视频?
Posted
技术标签:
【中文标题】如何使用 AVCaptureDeviceFormat 从 iPhone 录制延时视频?【英文标题】:How to record timelapse video from iPhone using AVCaptureDeviceFormat? 【发布时间】:2017-07-01 12:22:34 【问题描述】:我正在尝试通过 iphone 录制延时视频。我已经让它适用于慢动作(通过捕获可能的最大帧数),速度为 120 fps。
现在我正在尝试反转逻辑以捕获尽可能少的帧,以实现延时功能。
代码流程是这样的:
从 AVCaptureDevice 的可用设备格式中查询所有支持的帧范围。
检查帧速率是否低于或等于所需的 20 fps 并且尺寸是否等于或大于 1920*1080。
一切正常,除了当我按下记录时,我得到"AVCaptureMovieFileOutput - no active/enabled connections"
异常。我只使用提供的帧速率和范围之一,为什么会出现此异常?
30 fps 时一切正常。
#define kTimelapseRequiredFPS = 20
#define kMinRequiredDimensions (1920*1080)
- (void)configureCameraForSlowMoRecording:(AVCaptureDevice *)currentCaptureDevice
[_captureSession beginConfiguration];
AVCaptureDeviceFormat *bestFormat = nil;
AVFrameRateRange *bestFrameRateRange = nil;
for ( AVCaptureDeviceFormat *format in [currentCaptureDevice formats] )
//NSLog(@"Format: %@", format);
CMFormatDescriptionRef videoInfo = [format formatDescription];
double videoWidth = CMVideoFormatDescriptionGetDimensions(videoInfo).width;
double videoHeight = CMVideoFormatDescriptionGetDimensions(videoInfo).height;
double dimensions = videoWidth * videoHeight;
for ( AVFrameRateRange *range in format.videoSupportedFrameRateRanges )
//NSLog(@"Range: %@", range);
if ((range.maxFrameRate <= kTimelapseRequiredFPS) && (dimensions >= kMinRequiredDimensions))
bestFormat = format;
bestFrameRateRange = range;
if ( bestFormat )
NSLog(@"Final format: %@, Final range %@", bestFormat, bestFrameRateRange);
if ( [currentCaptureDevice lockForConfiguration:NULL] == YES )
currentCaptureDevice.activeFormat = bestFormat;
currentCaptureDevice.activeVideoMinFrameDuration = bestFrameRateRange.minFrameDuration;
currentCaptureDevice.activeVideoMaxFrameDuration = bestFrameRateRange.minFrameDuration;
[currentCaptureDevice unlockForConfiguration];
[_captureSession commitConfiguration];
这是 20 fps 的帧速率和范围的日志:
Format: <AVCaptureDeviceFormat: 0x1765f7a0 'vide'/'420v' 2592x1936, 1- 20 fps, fov:56.700, max zoom:153.00 (upscales @1.26), AF System:1, ISO:46.0-736.0, SS:0.000018-1.000000>
Range: <AVFrameRateRange: 0x176556d0 1 - 20>
Format: <AVCaptureDeviceFormat: 0x1765f750 'vide'/'420f' 2592x1936, 1- 20 fps, fov:56.700, max zoom:153.00 (upscales @1.26), AF System:1, ISO:46.0-736.0, SS:0.000018-1.000000>
Range: <AVFrameRateRange: 0x1750db10 1 - 20>
Format: <AVCaptureDeviceFormat: 0x1765f740 'vide'/'420v' 3264x2448, 1- 20 fps, fov:56.700, max zoom:153.00 (upscales @1.00), AF System:1, ISO:46.0-736.0, SS:0.000018-1.000000>
Range: <AVFrameRateRange: 0x1750dc80 1 - 20>
Format: <AVCaptureDeviceFormat: 0x1765f6f0 'vide'/'420f' 3264x2448, 1- 20 fps, fov:56.700, max zoom:153.00 (upscales @1.00), AF System:1, ISO:46.0-736.0, SS:0.000018-1.000000>
Range: <AVFrameRateRange: 0x1751a260 1 - 20>
【问题讨论】:
【参考方案1】:不确定这是否解决了,但我一直在努力让慢动作工作,并且也不断收到"AVCaptureMovieFileOutput - no active/enabled connections"
(所以我真的想知道你是如何让它工作的:D)。但无论如何我解决了它,这里有一些我认为可能会解决你的问题的棘手问题:
-
确保在设置
activeFormat
之前设置了一些预设。事实证明,ios 不仅会自动处理其他事情。我所做的是在设置之前设置AVCaptureSession.Preset.hd1280x720
activeFormat
120fps。
完成上述操作后,我开始收到Error Domain=AVFoundationErrorDomain Code=-11803 "Cannot Record" UserInfo=0x152e60 NSLocalizedRecoverySuggestion=Try recording again., AVErrorRecordingSuccessfullyFinishedKey=false, NSLocalizedDescription=Cannot Record
。我找不到任何可能的原因 - 连接正常,会话正在运行。所以我再次按下录制按钮,它开始录制(哇,真的吗?只是字面上的“再试一次”?)我猜 iOS 只是有点发脾气,必须考虑更长的时间才能录制。所以我添加了一个递归函数给movieFileOutput
一些时间来记录。 (对不起,它是在 Swift 中)
fileprivate func startRecording(to moviePath: URL)
sessionQueue.async
self.movieFileOutput.startRecording(to: moviePath, recordingDelegate: self)
if self.movieFileOutput.isRecording
self.sessionQueue.asyncAfter(deadline: .now() + self.duration)
self.stopRecording()
else
self.startRecording(to: moviePath)
希望它会有所帮助(或者也许其他像我一样偶然发现这个线程的人。)
【讨论】:
以上是关于如何使用 AVCaptureDeviceFormat 从 iPhone 录制延时视频?的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?