Search code examples
iosswiftvideooverlayavvideocomposition

AVVideoComposition applying filter handler not call


I want to add an overlay image into a video. I use AVVideoComposition and CIFilter to do this, but AVAsynchronousCIImageFilteringRequest handler not called. I put some breakpoints (line debugPrint"Here", request.finish), but XCode doesn't hit the breakpoints. enter image description here

I got the video, but doesn't have the watermark.

func watermark(video asset: AVAsset, with image: UIImage, output outURL: URL) {
        guard let watermarkImage = CIImage(image: image) else {
            return
        }

        let context = CIContext(options: nil)

        let videoComposition = AVVideoComposition(asset: asset) { (request) in
            debugPrint("Here")
            let source = request.sourceImage.clampedToExtent()

            let watermarkFilter = CIFilter(name: "CISourceOverCompositing")

            watermarkFilter?.setValue(source, forKey: kCIInputBackgroundImageKey)

            let transform = CGAffineTransform(translationX: request.sourceImage.extent.width - watermarkImage.extent.width - 10, y: 10)
            watermarkFilter?.setValue(watermarkImage.transformed(by: transform), forKey: kCIInputImageKey)
            guard let outputImage = watermarkFilter?.outputImage else {
                return
            }

            request.finish(with: outputImage, context: context)
        }

        let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)
        exporter?.outputFileType = .mov
        exporter?.outputURL = outURL
        exporter?.videoComposition = videoComposition
        exporter?.exportAsynchronously { [weak exporter] in
            guard let export = exporter else {
                return
            }

            switch export.status {
            case  .failed:
                print("failed \(exporter?.error)")
                break
            case .cancelled:
                print("cancelled \(exporter?.error)")
                break
            case .completed:
                print("complete")
            default:
                print("default")
            }
        }
    }

Solution

  • You shouldn't use passthrough preset with CI filtering. Try using another preset that defines a video format instead.

    This docs doesn't mention CI filtering specifically but it states that using passthrough preset would lead to layer instructions being ignored. I would expect it is the same for CI filtering.

    Important: If you export a video composition with an AVAssetExportSession object and specify the AVAssetExportPresetPassthrough export preset to let all tracks pass through, the transform defined in the video composition instruction (AVMutableVideoCompositionLayerInstruction) will not be applied. You must change the export preset to one that defines a video format (AVAssetExportPresetMediumQuality, for example) for the transform to be applied.