如何使用AVCaptureDeviceFormat从iPhone录制间隔拍摄视频?

时间:2017-07-01 12:22:35

标签: ios iphone avcapturesession avcapturemoviefileoutput

我正在尝试通过iphone录制间隔拍摄视频。我已经让它用于慢动作(通过捕获最大帧),120 fps。

现在我试图颠倒逻辑以捕获可能的最少帧,以实现游戏中时光倒流功能。

代码流程如下:

  1. 从AVCaptureDevice的可用设备格式查询所有支持的帧范围。

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

  3. 一切正常,但是当我按下记录时,我得到"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 个答案:

答案 0 :(得分:0)

不确定这是否已经解决,但是我在努力使慢动作工作,并且不断获得"AVCaptureMovieFileOutput - no active/enabled connections"(所以我真的很想知道你是如何让它工作的:D)。但无论如何我解决了它,这里有一些棘手的东西我认为可以解决你的问题:

  1. 确保在设置activeFormat之前设置了一些预设。原来iOS不会自动处理其他东西。我做的是在设置之前设置AVCaptureSession.Preset.hd1280x720 activeFormat到120fps的那个。
  2. 完成上述操作后,我开始Error Domain=AVFoundationErrorDomain Code=-11803 "Cannot Record" UserInfo=0x152e60 {NSLocalizedRecoverySuggestion=Try recording again., AVErrorRecordingSuccessfullyFinishedKey=false, NSLocalizedDescription=Cannot Record}。我找不到任何可能的原因 - 连接很好,会话正在运行。所以我再次按下录制按钮,它开始录制(哇,真的吗?只是字面意思“再试一次”?)我猜iOS只是发脾气,不得不考虑更长一点记录。所以我添加了一个递归函数来给movieFileOutput一些时间来记录。 (对不起,这是在斯威夫特)

    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)
            }
        }
    }
    
  3. 希望它会有所帮助(或者也许是其他只是像我一样偶然发现这个问题的人。)