2

I have a video I'm overlaying on top of another video, where the overlay video has a transparent background. I'm doing this with AVMutableComposition where I just add the tracks and it works great; AVPlayer plays it fine. The problem is when I try to export the video.

When I export the video I still see the overlay but its background is no longer transparent. It adds a weird filter to the video behind it. The codec of the overlay is AAC, HEVC with Alpha, which is the only way I could make it work for the composition.

Here is the code to export, where the outputURL ends with .mp4:

func getVideoUrl(composition: AVMutableComposition, vidComp: AVMutableVideoComposition, audioMix: AVMutableAudioMix, overlays: [Overlay], completion: @escaping (_ success: Bool, _ videoID: String?, _ videoName: String?) -> ()) {

    var preset = "AVAssetExportPreset1920x1080"
    
    exportSession = AVAssetExportSession(asset: composition, presetName: preset)
    
    guard let exportSession = exportSession else {
        completion(false, nil, nil)
        return
    }
    
    exportSession.videoComposition = vidComp
    exportSession.audioMix = audioMix
    exportSession.outputURL = uniqueURLForSave()
    exportSession.outputFileType = AVFileType.mp4
    exportSession.shouldOptimizeForNetworkUse = true
    
    exportSession.exportAsynchronously {
        switch exportSession.status {
        case .completed:
            UISaveVideoAtPathToSavedPhotosAlbum(exportSession.outputURL!.relativePath, self, nil, nil)
            
            completion(true, self.videoUrlID, self.videoName)
        case .cancelled:
            print("Cancelled")
            completion(false, nil, nil)
        case .failed:
            print("Failed: \(exportSession.error.debugDescription)")
            completion(false, nil, nil)
        default:
            print("Other Error")
            completion(false, nil, nil)
        }
    }
}

I've also tried outputs with .mov and presets like AVAssetExportPresetHEVC1920x1080 and AVAssetExportPresetHEVC1920x1080WithAlpha. Anyone know how to export the video so it respects the transparency? I'd rather keep it as an mp4 if possible.

Here's a screenshot of what the video looks like mid overlay, and then after the overlay video is done playing.

enter image description here

enter image description here

kerbelda
  • 325
  • 1
  • 4
  • 14

1 Answers1

0

To solve this issue you will need to use AVVideoCompositing. Inside the compositor you will need to grab the CIImage of the overlay and manually correct the color space. For example, in my case I, inspected the overlay color space and found that

let context = CIContext(options: [CIContextOption.workingColorSpace: kCFNull!])
if let cgImage:CGImage = context.createCGImage(ciImage, from: ciImage.extent, format: .RGBA16, colorSpace: CGColorSpace.init(name: CGColorSpace.itur_709)!){
//result of the image is a fixed color space.  //removes a filmy look over image
}

I find this interesting because AVPlayerLayer must do a colorspace correction out of the box but AVAssetExportSession does not. There are other colorspaces that might fit as I found that .extendedLinearSRGB was also close. But I do suggest inspecting your file.

agibson007
  • 4,173
  • 2
  • 19
  • 24