Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer playback fails while AVAssetExportSession is active as of iOS 10

AVPlayer will randomly just play audio, not showing the video track...

Playing video correctly with AVPlayer while having an active compression session of AVAssetExportSession:exportAsynchronouslyWithCompletionHandler is now failing. It seems it causes some instability that persists until the app goes into the background and comes back.

Examining AVURLAsset when video playback fails, there is a video track even though there is no video output. I also don't get any errors from the compressor or the other playback components... The problem happens even for a while after the compression session has returned.

I've tried separate threading in different ways with no success.

It seems that as of iOS 10 there is something going on under the hood that causes some sort of conflict between both processes...

like image 959
Andres Canella Avatar asked Sep 18 '16 17:09

Andres Canella


2 Answers

Just heard from Apple DTS. They also agree this points to an Apple iOS bug and asked me to log it.

I cut out usage of AVAssetExportSession altogether and it solved the issue. So calling AVAssetExportSession in combination with other AV methods is what causes the iOS instability.

In my case I was usingAVAssetExportSession for post capture compression. So instead I used AVAssetWriter to sample each frame in real-time to the format I needed...

This should be fixed soon by Apple, hopefully.

like image 185
Andres Canella Avatar answered Oct 06 '22 15:10

Andres Canella


I found a solution to my problem. Like Sami said, the issue appears to be in AVVideoCompositionCoreAnimationTool which I was using to watermark my video. I shifted to using a CIFilter, which actually had cleaner code anyway.

I removed everything with CoreAnimationTool and used this (mixComposition is my AVMutableComposition):

let watermarkFilter = CIFilter(name: "CISourceOverCompositing")!
let watermarkImage = CIImage(image: #imageLiteral(resourceName: "watermark"))!
let videoComposition = AVVideoComposition(asset: mixComposition) { (filteringRequest) in
    let source = filteringRequest.sourceImage.clampingToExtent()
    watermarkFilter.setValue(source, forKey: "inputBackgroundImage")
    let transform = CGAffineTransform(translationX: filteringRequest.sourceImage.extent.width - watermarkImage.extent.width - 2, y: 0)
    watermarkFilter.setValue(watermarkImage.applying(transform), forKey: "inputImage")
    filteringRequest.finish(with: watermarkFilter.outputImage!, context: nil)
}

and then in the AVAssetExportSession added this:

exporter!.videoComposition = videoComposition

Hope that helps somebody!

like image 30
Ethan Avatar answered Oct 06 '22 14:10

Ethan