添加叠加层时,捕获的视频非常滞后

时间:2017-09-08 14:58:01

标签: swift avfoundation core-image avassetwriter cifilter

我正在使用AVAssetWriter构建应用程序,我在其中为视频添加叠加层。当我不尝试添加叠加层时,它非常有用。但是当我添加叠加层时,视频看起来会从一半裁剪掉(正如您在屏幕截图中看到的那样)。

这是我的addOverlayToImage函数:

func addOverlayToImage(from filteredImage: UIImage) -> UIImage {
   UIGraphicsBeginImageContextWithOptions(self.imageView.frame.size, false, 1.0);
   self.imageView.layer.render(in: UIGraphicsGetCurrentContext()!)
   let imageWithText = UIGraphicsGetImageFromCurrentImageContext()
   UIGraphicsEndImageContext();
   return imageWithText! 
}

我在captureOutput中调用函数:

func captureOutput(_ captureOutput: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection) {
   self.bufferVideoQueue.async() {
     let imageWithOverlay = self.addOverlayToImage(from: self.filteredImage)
     let buffer = self.imageToBuffer(from: imageWithOverlay)
     self.assetWriterPixelBufferInput?.append(buffer!, withPresentationTime: self.currentTime)
   }
}

imageToBuffer函数:

func imageToBuffer(from image: UIImage) -> CVPixelBuffer? {
    let attrs = [
        String(kCVPixelBufferCGImageCompatibilityKey) : kCFBooleanTrue,
        String(kCVPixelBufferCGBitmapContextCompatibilityKey) : kCFBooleanTrue
    ] as [String : Any]
    var buffer : CVPixelBuffer?
    let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs as CFDictionary, &buffer)
    guard (status == kCVReturnSuccess) else {
        return nil
    }

    CVPixelBufferLockBaseAddress(buffer!, CVPixelBufferLockFlags(rawValue: 0))
    let pixelData = CVPixelBufferGetBaseAddress(buffer!)

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    let context = CGContext(data: pixelData, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(buffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)

    context?.translateBy(x: 0, y: image.size.height)
    context?.scaleBy(x: 1.0, y: -1.0)

    UIGraphicsPushContext(context!)
    image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
    UIGraphicsPopContext()
    CVPixelBufferUnlockBaseAddress(buffer!, CVPixelBufferLockFlags(rawValue: 0))

    return buffer
}

视频截图:

enter image description here

2 个答案:

答案 0 :(得分:1)

您是否尝试过配置AVAssetWriterInput以实时指定数据(将expectedMediaDataInRealTime设置为true)?这在写入实时(实时摄像机)数据时会产生很大的不同,如果设置不正确,可能导致输出滞后。

https://developer.apple.com/documentation/avfoundation/avassetwriterinput

https://developer.apple.com/documentation/avfoundation/avassetwriterinput/1387827-expectsmediadatainrealtime

答案 1 :(得分:0)

我没有明确的答案,因为我没有看到这个错误,但我认为它可能会发生,因为你在帧上进行的处理花费的时间比帧时间长(1/30秒) ,可能)。

我的建议是尽可能减少时间。我可以看到您正在从UIImage创建UIView,然后将其转换为CVPixelBuffer

所有这一切都发生在每一帧,但是,您的内容似乎不是需要来改变每一帧。

我建议您存储缓冲区并在captureOutput(...)中添加一些逻辑以查看内容是否已更改。如果它没有你可以使用存储的缓冲区,如果有,你可以重新计算它,但现在这只会发生每分钟(我假设从你的截图),所以它不应该影响视频。

最后,您正在异步执行代码,这可能会导致问题,因此我建议您删除该部分,然后在委托方法中执行该代码。 (注意:如果文档指示您异步执行此操作,请忽略此操作)