ios - 如何以每秒240帧的速度录制和保存?

标签 ios swift avcapturesession

我需要以手机的最大帧速率 (240 fps) 从 iPhone Xs 录制和保存视频。保存的文件始终以 30 fps 结束。我浏览了十几个指南/文档/Stack Overflow 帖子,但尚未找到正确的解决方案。我已经通过在 VLC 中打开录制的文件以及提取和计算帧数进行了测试。

我做错了什么?

环境:Xcode 10.1,构建目标 iOS 12.1,在运行 iOS 12.1.2 的 iPhone Xs 上测试

在这里,我访问设备并将其配置为它支持的最佳帧速率:

override func viewDidLoad() {
    super.viewDidLoad()
    let deviceDiscoverSession = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
    guard let backCameraDevice = deviceDiscoverSession else {
        print("Failed to open back, wide-angle camera")
        return
    }
    self.currentDevice = backCameraDevice
    do {
        let input = try AVCaptureDeviceInput(device: backCameraDevice)
        // configureDevice() // putting this here makes no difference
        self.session.addInput(input)
        configureDevice()
    } catch {
        print(error)
        return
    }
}

func configureDevice() {
    var bestFormat: AVCaptureDevice.Format? = nil
    var bestFrameRateRange: AVFrameRateRange? = nil
    var bestPixelArea: Int32 = 0
    for format in currentDevice!.formats {
        let dims: CMVideoDimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription)
        let pixelArea: Int32 = dims.width * dims.height
        let ranges = format.videoSupportedFrameRateRanges
        for range in ranges {
            if bestFrameRateRange==nil || range.maxFrameRate > bestFrameRateRange!.maxFrameRate || ((range.maxFrameRate == bestFrameRateRange!.maxFrameRate) && (pixelArea > bestPixelArea)) {
                bestFormat = format as AVCaptureDevice.Format
                bestFrameRateRange = range
                bestPixelArea = pixelArea
            }
        }
    }
    do {
        try currentDevice!.lockForConfiguration()
        if let best_format = bestFormat {
            currentDevice!.activeFormat = best_format
            currentDevice!.activeVideoMinFrameDuration = bestFrameRateRange!.minFrameDuration
            currentDevice!.activeVideoMaxFrameDuration = bestFrameRateRange!.maxFrameDuration
        }
    } catch {
        print(error)
    }

    let movieFileOutput = AVCaptureMovieFileOutput()

    if self.session.canAddOutput(movieFileOutput) {
        self.session.beginConfiguration()
        self.session.addOutput(movieFileOutput)
        self.session.sessionPreset = .high
        if let connection = movieFileOutput.connection(with: .video) {
            if movieFileOutput.availableVideoCodecTypes.contains(.h264) {
                movieFileOutput.setOutputSettings([AVVideoCodecKey:
                    AVVideoCodecType.h264], for: connection)
            }
        }
        self.session.commitConfiguration()
        self.movieFileOutput = movieFileOutput
    }
    currentDevice!.unlockForConfiguration()
}

当用户停止录制时,我调用了一个部分包含以下代码的函数来将文件保存到临时目录(稍后移动到应用程序的文档目录)

sessionQueue.async {
    if !self.isRecording {
        self.isRecording = true
        let movieFileOutputConnection = self.movieFileOutput!.connection(with: .video)
        movieFileOutputConnection?.videoOrientation = .landscapeRight
        let availableVideoCodecTypes = self.movieFileOutput!.availableVideoCodecTypes
        if availableVideoCodecTypes.contains(.h264) {
           self.movieFileOutput!.setOutputSettings([AVVideoCodecKey: AVVideoCodecType.h264], for: movieFileOutputConnection!)
        }
        let outputFileName = NSUUID().uuidString
        let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mp4")!)
        self.movieFileOutput?.startRecording(to: URL(fileURLWithPath: outputFilePath), recordingDelegate: self)
    } else {
        self.movieFileOutput?.stopRecording()
        self.isRecording = false
    }
}

典型的答案似乎是 configure the device after adding it to the session .在添加到 session 之前或之后调用配置似乎没有什么不同。

我已经尝试在 self.movi​​eFileOutput?.startRecording() 调用之前以及上面显示的位置配置 movieFileOutput。两者给出相同的结果。

最佳答案

我通过深入阅读 https://stackoverflow.com/a/41109637/292947 弄明白了这一点

configureDevice() 中,我正在设置 self.session.sessionPreset = .high 而实际上我需要设置 self.session.sessionPreset = .inputPriority 这是 Swift 4 等同于上述答案中建议的 AVCaptureSessionPresetInputPriority 值。

VLC shows 240 fps

关于ios - 如何以每秒240帧的速度录制和保存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54351972/

相关文章:

ios - 如何知道 MPMusicPlayerController 何时自然改变播放项目

ios - 在swift中使用json发送参数

ios - AVCaptureSession addInput 导致背景音频出现故障

ios - Podfile.lock没有这样的文件或目录

ios - 如果 Macro 设置为 1,则排除目标中的类

ios - 在 Swift 中的数组中添加引号 (")

iphone - 在 iOS 中使用 AVCaptureMovieFileOutput 和 AVCaptureVideoDataOutput 暂停和恢复视频捕获

ios - 视频输入时拍照

ios - 在另一个 UIViewController 之上呈现一个模糊的 UIViewController

ios - HM-10 和 iOS/iBeacon。两人之间的沟通