如何使用 AVVideoCompositionCoreAnimationTool 获取自定义 CIFilter 以在 CALayer 上工作以进行导出

How can I get a custom CIFilter to work on a CALayer for export using the AVVideoCompositionCoreAnimationTool

使用依赖于自定义输入参数的自定义 CIFilter 时,一旦将过滤器设置为 CALayer backgroundFilters,就不会使用这些参数,因此您可以使用 [=17] 将其渲染为视频=] 输入参数不再使用,貌似CALayer新建了一个CIFilter,并没有添加设置的参数。

使用默认选项:

let layer = CALayer()
let filter = CIFilter(name: "CustomFilter")!
filter.setValue(10, forKey: "value")
layer.backgroundFilters = [filter]

或:

let layer = CALayer()
let filter = CIFilter(name: "CustomFilter", options: ["value": 10])!
layer.backgroundFilters = [filter]

或使用 Apple 在手册中提到的内容:

let layer = CALayer()
let filter = CIFilter(name: "CustomFilter")!
filter.name = "myFilter"
layer.backgroundFilters = [filter]
layer.setValue(10, forKeyPath: "backgroundFilters.myFilter.value"

无论什么顺序,什么值,如果自定义过滤器是这样定义的:

class CustomFilter: CIFilter {
    override class var supportsSecureCoding: Bool {
        return true
    }

    
    @objc dynamic var inputImage: CIImage?
    @objc dynamic var value: NSNumber?

    override public var outputImage: CIImage? {
        guard let image = inputImage else {
            return nil
        }

        // return the actual stuff you want done here!
    }
}

甚至使用以下方式注册:

class CustomFilterRegister: CIFilterConstructor {
    static func register() {
        CIFilter.registerName(
            "CustomFilter", constructor: CustomFilterRegister(),
            classAttributes: [
                kCIAttributeFilterCategories: [
                    kCICategoryVideo,
                    kCICategoryStillImage,
                    "CustomFilters"
                ],
            ])
    }
    
    func filter(withName name: String) -> CIFilter? {
        switch name {
        case "CustomFilter":
            return CustomFilter()
        default:
            return nil
        }
    }
}

CALayer 不受 value 参数中设置的影响。

为了 CALayers 与自定义 CIFilter 一起工作,似乎有 2 件重要的事情需要添加。

  1. 您需要覆盖输入键:
override var inputKeys: [String] {
   return [kCIInputImageKey, "value"]
}
  1. 您需要像这样声明所有使用的参数:
override var attributes: [String : Any] {
  return [
      kCIAttributeFilterDisplayName: "Custom Filter",
      kCIAttributeFilterName: "CustomFilter",
      kCIAttributeFilterCategories: [
          kCICategoryVideo,
          kCICategoryStillImage,
          "CustomFilters",
      ],
      kCIInputImageKey: [
          kCIAttributeIdentity: 0,
          kCIAttributeClass: "CIImage",
          kCIAttributeDisplayName: "Image",
          kCIAttributeType: kCIAttributeTypeImage
      ],
      #keyPath(value): [
          kCIAttributeIdentity: 0,
          kCIAttributeClass: "NSNumber",
          kCIAttributeDisplayName: "Custom value",
          kCIAttributeMin: 0,
          kCIAttributeMax: 5,
          kCIAttributeSliderMin: 0,
          kCIAttributeSliderMax: 5,
          kCIAttributeType: kCIAttributeTypeScalar
      ],
      kCIOutputImageKey: [
          kCIAttributeClass: "CIImage",
          kCIAttributeDisplayName: "Output Image",
          kCIAttributeType: kCIAttributeTypeImage
      ]
  ]
}

希望我能为你们中的一些人节省大量时间来解决这个问题!