【问题标题】:How to apply CIFilter to video in Swift without waiting to process如何在 Swift 中将 CIFilter 应用于视频而不等待处理
【发布时间】:2020-01-19 07:26:03
【问题描述】:

我目前正在我的一个应用中开发一项功能,用户可以在其中将照片和视频添加到帖子中。他们有能力录制视频或拍照,但之后我想通过应用滤镜或更改亮度、对比度、曝光等方式让他们完全控制输出...

这对于照片来说相对容易。为了简化工作流程,我使用了一个名为 BBMetalImage 的第三方库。这很好用,我可以对照片和视频应用过滤器,但处理视频需要很长时间,我不希望我的用户这样做。应用过滤器时,处理一个 15 秒的剪辑可能需要 20 到 30 秒以上的时间。

我目前是这样做的:

var lookupFilterName: String! = "lookup_1"
let outputURL = URL(fileURLWithPath: "\(NSTemporaryDirectory())\(NSUUID().uuidString).mp4")
try? FileManager.default.removeItem(at: outputURL)
videoWriter = BBMetalVideoWriter(url: outputURL, frameSize: BBMetalIntSize(width: 480, height: 600))
videoSource = BBMetalVideoSource(url: currentVideoURL!)
videoSource.audioConsumer = videoWriter
if(filter != 0) {
    lookupFilterName = "lookup_\(filter)"
}
let lookupFilter = BBMetalLookupFilter(lookupTable: UIImage(named: lookupFilterName)!.bb_metalTexture!)
videoSource.add(consumer: lookupFilter).add(consumer: videoWriter)
videoSource.audioConsumer = videoWriter
videoWriter.start()
videoSource.start { [weak self] (_) in
    guard let self = self else { return }
    self.videoWriter.finish {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            if(self.currentVideoURL != nil) {
                self.queuePlayer?.pause()
                self.queuePlayer?.removeAllItems()
                if let playerLayer = self.playerLayer {
                    playerLayer.removeFromSuperlayer()
                }
                self.currentFinalVideoURL = outputURL
                let playerItem = AVPlayerItem(url: outputURL)
                self.queuePlayer = AVQueuePlayer(items: [playerItem])
                self.playerLayer = AVPlayerLayer(player: self.queuePlayer)
                self.playerLooper = AVPlayerLooper(player: self.queuePlayer!, templateItem: playerItem)
                self.videoPreview.layer.addSublayer(self.playerLayer!)
                self.playerLayer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width * 1.25)
                self.playerLayer?.backgroundColor = UIColor.black.cgColor
                self.queuePlayer?.play()
                self.videoWriter = nil
                self.videoSource = nil
            } else {
                self.videoWriter = nil
                self.videoSource = nil
            }
        }
    }
}

请不要误会我的意思。它完成了这项工作:它返回应用了过滤器的视频。基本上发生的事情是,它获取原始视频的源 URL,对其应用过滤器,将其写入另一个临时路径,然后将此视频显示给用户。

在我看来,这必须更快。我开始研究其他应用程序,尤其是 Instagram,当您应用过滤器时,它会立即更改(甚至不需要一秒钟)并继续播放视频而无需从第一帧重新开始。这才是我真正想要的。

我已经对此进行了一些研究,并认为我应该使用 CIFilter,因为 Core Image 提供了一种非常快速且可靠的方式来处理照片(和视频?)。

所以我的问题是:

  1. 我能否在使用 CIFilter 时应用定制的查找过滤器或 LUT,还是仅限于 Core Image 框架中提供的内置过滤器(例如 GaussianBlur 等)?
  2. 我应该如何“实时”更改视频,而不会对最终用户造成延迟?我在某处读到这是使用缓冲区完成的,之后视频的每一帧都以所需的效果进行操作并实时播放。关于如何实现这一目标的任何参考或示例?我不知道从哪里开始处理这个具体问题。我还希望能够在用户停止编辑时导出此视频(滤镜、亮度、对比度……)。

干杯!欢迎提供所有信息。

【问题讨论】:

    标签: ios swift video-processing core-image cifilter


    【解决方案1】:

    AVFoundation 框架可以轻松地逐帧处理视频。它每次都在当前时间从视频中生成像素缓冲区帧,并让您根据需要在帧上添加任何效果(过滤器、亮度、对比度任何您想要的)。实时处理帧可以在 GPU 上完成。 OpenGLMetal 这些都可以用于此。它还将帮助您使用自己的定制过滤器。您可以关注此link 开始。

    【讨论】:

    • 不一定需要在 GPU 上完成。 Accelerate.vImage 的速度足以实时处理视频帧,请参阅:developer.apple.com/documentation/accelerate/vimage/…
    • 感谢您的信息
    • 感谢 Al Mamun Akash。我正在调查它! @SimonGladman 最好使用 vImage 还是 Metal,特别是我现在正在使用的 BBMetalImage 库,也是一种可能性吗?在 GPU 上执行此操作会影响我的应用程序吗?
    • 您可以使用 Metal 或 Accelerate.vImage 进行实时视频处理。哪个“更好”在很大程度上取决于上下文和您的要求。您可能应该探索这两种技术来决定哪种技术最适合您。
    猜你喜欢
    • 2012-05-05
    • 2016-12-31
    • 2011-04-23
    • 1970-01-01
    • 2021-06-14
    • 2018-02-17
    • 2014-07-14
    • 2017-06-29
    • 2014-02-23
    相关资源
    最近更新 更多