Ios 如何使用AVCaptureDeviceFormat从iPhone录制timelapse视频?

Ios 如何使用AVCaptureDeviceFormat从iPhone录制timelapse视频?,ios,iphone,avcapturesession,avcapturemoviefileoutput,Ios,Iphone,Avcapturesession,Avcapturemoviefileoutput,我正在尝试通过iphone录制timelapse视频。我已经让它为慢动作工作了(通过捕捉尽可能多的帧),每秒120帧 现在,我尝试反转逻辑以捕获尽可能少的帧,以实现timelapse功能 代码流如下所示: 从AVCaptureDevice的可用设备格式中查询所有支持的帧范围 检查帧速率是否低于或等于所需的20 fps,尺寸是否等于或大于1920*1080 除了按下record键时出现“AVCaptureMovieFileOutput-无活动/启用的连接”异常外,所有操作都正常。我只使用提供的帧速

我正在尝试通过iphone录制timelapse视频。我已经让它为慢动作工作了(通过捕捉尽可能多的帧),每秒120帧

现在,我尝试反转逻辑以捕获尽可能少的帧,以实现timelapse功能

代码流如下所示:

  • 从AVCaptureDevice的可用设备格式中查询所有支持的帧范围

  • 检查帧速率是否低于或等于所需的20 fps,尺寸是否等于或大于1920*1080

  • 除了按下record键时出现“AVCaptureMovieFileOutput-无活动/启用的连接”异常外,所有操作都正常。我只使用提供的帧速率和范围中的一个,为什么会出现此异常

    所有这些都能以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];
            }
    
    #定义ktimeReleaseRequiredFPS=20
    #定义KMINR要求的尺寸(1920*1080)
    -(无效)配置CameraforFlowMoreRecording:(AVCaptureDevice*)currentCaptureDevice
    {
    [[捕获会话开始配置];
    AVCaptureDeviceFormat*bestFormat=nil;
    AVFrameRateRange*bestFrameRateRange=nil;
    用于(在[currentCaptureDevice formats]中的AVCaptureDeviceFormat*格式)
    {
    //NSLog(@“格式:%@”,格式);
    CMFormatDescriptionRef videoInfo=[format formatDescription];
    双videoWidth=CMVideoFormatDescriptionGetDimensions(videoInfo).width;
    双视频高度=CMVideoFormatDescriptionGetDimensions(videoInfo).height;
    双尺寸=视频宽度*视频高度;
    用于(格式为AVFrameRateRange*范围。videoSupportedFrameRateRanges)
    {
    //NSLog(@“范围:%@”,范围);
    如果((range.maxFrameRate=kMinRequiredDimensions))
    {
    最佳格式=格式;
    bestFrameRateRange=范围;
    }
    }
    }
    if(最佳格式)
    {
    NSLog(@“最终格式:%@,最终范围%@”,最佳格式,最佳帧率范围);
    如果([currentCaptureDevice lockForConfiguration:NULL]==是)
    {
    currentCaptureDevice.activeFormat=bestFormat;
    currentCaptureDevice.activeVideoMinFrameDuration=bestFrameRateRange.minFrameDuration;
    currentCaptureDevice.activeVideoMaxFrameDuration=bestFrameRateRange.minFrameDuration;
    [currentCaptureDevice unlockForConfiguration];
    }
    }
    [_CaptureSessionCommitteConfiguration];
    }
    
    以下是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>
    
    格式:
    范围:
    格式:
    范围:
    格式:
    范围:
    格式:
    范围:
    
    不确定这个问题是否得到解决,但我一直在努力以慢动作工作,并不断得到
    “AVCaptureMovieFileOutput-无活动/启用的连接”
    (因此我真的很想知道如何让它工作:D)。但不管怎么说,我解决了这个问题,这里有一些棘手的东西,我认为也可以解决你的问题:

  • 在设置
    activeFormat
    之前,请确保设置了一些预设。事实证明,iOS不会自动处理其他东西。我所做的是在设置
    activeFormat
    转换为每秒120帧的格式
  • 完成上述操作后,我开始获取
    Error-Domain=AVFoundationErrorDomain-code=-11803“无法录制”UserInfo=0x152e60{nsLocalizedRecoverysSuggestion=再次尝试录制,AVErrorRecordingSuccessfullyFinishedKey=false,NSLocalizedDescription=无法录制}
    。我找不到任何可能的原因-连接正常,会话正在运行。所以我再次按下录制按钮,它开始录制(哇,真的吗?只是字面上的“再试一次”?)我想iOS只是有点脾气,需要考虑更长的时间才能录制。因此,我添加了一个递归函数,以给
    movieFileOutput
    一些记录时间。(对不起,是Swift)


  • 希望它能有所帮助(或者像我一样偶然发现这条线索的其他人)。

    不确定这是否解决了,但我一直在缓慢地工作,并且不断地得到
    “AVCaptureMovieFileOutput-没有活动/启用的连接”
    (所以我真的很想知道如何让它工作:D)。但不管怎么说,我解决了这个问题,这里有一些棘手的东西,我认为也可以解决你的问题:

  • 在设置
    activeFormat
    之前,请确保设置了一些预设。事实证明,iOS不会自动处理其他东西。我所做的是在设置
    activeFormat
    转换为每秒120帧的格式
  • 完成上述操作后,我开始获取
    Error-Domain=AVFoundationErrorDomain-code=-11803“无法录制”UserInfo=0x152e60{nsLocalizedRecoverysSuggestion=再次尝试录制,AVErrorRecordingSuccessfullyFinishedKey=false,NSLocalizedDescription=无法录制}
    。我找不到任何可能的原因-连接正常,会话正在运行。所以我再次按下录制按钮,它开始录制(哇,真的吗?只是字面上的“再试一次”?)我想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)
            }
        }
    }