title: How to apply CIFilter to video in Swift without waiting to process
body: <p>I am currently developing a feature in one of my apps where users can add photos and videos to a post. They have the ability to record video or taking a picture, but afterwards I want to give them full control over the output by applying filters or changing brightness, contrast, exposure, ...</p>
  
  <p>This is relatively easy for photo. To streamline the workflow, I use a third party library called <a href="https://github.com/Silence-GitHub/BBMetalImage" rel="nofollow noreferrer">BBMetalImage</a>. This works great, I can apply filters to photo as well as video, but it takes a long time to process the video, which I don't want for my users. A 15 second clip can quickly take upwards of 20 - 30 seconds to process when applying a filter.</p>
  
  <p>I currently do it like this:</p>
  
  <pre><code>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
              }
          }
      }
  }
  </code></pre>
  
  <p>Please don't get me wrong. It does the job: it returns the video with the filter applied. Basically what's happening is, it takes the source URL of the original video, applies a filter to it, writes it to another temporary path and then displays this video to the user.</p>
  
  <p>In my opinion, this has to be possible much quicker. I started looking at other applications, especially Instagram, where, when you apply a filter, it changes immediately (doesn't even take a second) and continues playing the video without restarting from the first frame. This is what I actually want.</p>
  
  <p>I looked into this a bit already and figured out I should use CIFilter, because Core Image provides a very fast and reliable way to manipulate photo (and video?).</p>
  
  <p>So my questions are:</p>
  
  <ol>
  <li>Will I be able to apply custom-made lookup filters or LUTs when using CIFilter, or am I restricted to the built-in filters provided in the Core Image framework (such as GaussianBlur etc.)?</li>
  <li>How should I go about changing the video "in real time", without delay for the end user? I read somewhere that this is done using a buffer, after which each frame of the video is manipulated with the desired effect and played back in real time. Any reference or example on how to achieve this? I have no idea where to start on this specific matter. I would also like to be able to export this video when the user stopped editing (filters, brightness, contrast, ...).</li>
  </ol>
  
  <p>Cheers! All information is welcome.</p>