AVAssetWriter使输出闪烁并更改帧速率

问题描述

我正在使用AVFoundation创建一个应用程序,在该应用程序中,必须将摄像机的Feed延迟从0ms延迟到1000ms。

我有0.0的延迟时,我是从AVCaptureOutput提供的CVImageBuffer创建UIImage的,它工作得很好。

但是当我的延迟> 0.0时,我正在录制视频片段,对其进行编码,然后使用AVAssetWriter将其存储在文件中,然后在AVPlayer中播放。当我的延迟> 100ms,但值

我在做什么错了?

这是代码

func setupCamera() {
    captureSession.sessionPreset = AVCaptureSession.Preset.hd1920x1080

    let availableDevices = AVCaptureDevice.discoverySession(deviceTypes: [.builtInUltraWideCamera,.builtInWideAngleCamera],mediaType: .video,position: .back).devices

    if let device = availableDevices.first {
        captureDevice = device
        captureDevice.updateFormatWithPreferredVideoSpec(preferredSpec: AVCaptureDevice.VideoSpec(fps: 60,size: CGSize(width: 1920,height: 1080)))

        beginCameraSession()
    }
}


private func setupDeviceinput() {
    do {
        let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.addInput(captureDeviceInput)
    } catch {
        print(error.localizedDescription)
    }
}

private func setupDeviceOutput() {
    let dataOutput = AVCaptureVideoDataOutput().then {
        $0.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as String):NSNumber(value: kCVPixelFormatType_32BGRA)]
        $0.alwaysdiscardsLateVideoFrames = true
    }

    if captureSession.canAddOutput(dataOutput) {
        captureSession.addOutput(dataOutput)
    }

    captureSession.commitConfiguration()

    let queue = dispatchQueue(label: "com.captureQueue")
    dataOutput.setSampleBufferDelegate(self,queue: queue)
}

fileprivate func createWriterInput(for presentationTimeStamp: CMTime) {
    let fileManager = FileManager.default
    chunkOutputURL = fileManager.urls(for: .documentDirectory,in: .userDomainMask)[0].appendingPathComponent("chunk\(chunkNumber).mov")
    try? fileManager.removeItem(at: chunkOutputURL)

    assetWriter = try! AVAssetWriter(outputURL: chunkOutputURL,fileType: AVFileType.mov)
    assetWriter.shouldOptimizeforNetworkUse = true

    let outputSettings: [String: Any] = [AVVideoCodecKey:AVVideoCodecType.h264,AVVideoWidthKey: 1920,AVVideoHeightKey: 1080,AVVideoCompressionPropertiesKey: [AVVideoExpectedSourceFrameRateKey: 60,AVVideoAverageNonDroppableFrameRateKey: 60,AVVideoAverageBitRateKey: 60000000,AVVideoMaxKeyFrameIntervalDurationKey: 0.0,AVVideoAllowFrameReorderingKey: true]]

    assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video,outputSettings: outputSettings)
    assetWriterInput.expectsMediaDataInRealTime = true

    assetWriter.add(assetWriterInput)

    chunkNumber += 1
    chunkStartTime = presentationTimeStamp

    assetWriter.startWriting()
    assetWriter.startSession(atSourceTime: chunkStartTime)
}

// MARK: - Outputs

fileprivate func createImageOutput(from buffer: CMSampleBuffer) {
    guard let cvBuffer = CMSampleBufferGetimageBuffer(buffer) else {
        return
    }

    let ciImage = CIImage(cvImageBuffer: cvBuffer)
    let uiImage = UIImage(ciImage: ciImage)

    didOutputimage?(uiImage)
}

fileprivate func createVideoOutput(from buffer: CMSampleBuffer) {
    let presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(buffer)

    if assetWriter == nil {
        createWriterInput(for: presentationTimeStamp)
    } else {
        let chunkDuration = CMTimeGetSeconds(CMTimeSubtract(presentationTimeStamp,chunkStartTime))

        if chunkDuration > latency {
            assetWriter.endSession(atSourceTime: presentationTimeStamp)

            let newChunkURL = chunkOutputURL!
            let chunkAssetWriter = assetWriter!

            chunkAssetWriter.finishWriting { [weak self] in
                guard let strongSelf = self else { return }
                strongSelf.didOutputPlayerItem?(AVPlayerItem(url: newChunkURL))
            }

            createWriterInput(for: presentationTimeStamp)
        }
    }

    if !assetWriterInput.append(buffer) {
        print("append says NO: \(assetWriter.status.rawValue)")
    }
}

func captureOutput(_ output: AVCaptureOutput,didOutput sampleBuffer: CMSampleBuffer,from connection: AVCaptureConnection) {
    if latency == 0.0 {
        createImageOutput(from: sampleBuffer)
    } else {
        createVideoOutput(from: sampleBuffer)
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)