When playing a video exported from a AVAssetExportSession
, you hear audio long before seeing video. Audio plays right away, but video only appears after the recording loops several times (i.e., starts and finishes). In other words, you hear audio from the video multiple times before seeing any images.
We are using AutoLayout on iOS 8.
Using the following test, we isolated the problem to exportAsynchronouslyWithCompletionHandler
. In both code blocks, we play an existing video -- not one related to the export -- so the export process has been eliminated as a variable.
Code 1 plays both video & audio at the start whereas Code 2 only plays audio at the start and shows video after a delay of 10-60 seconds (after the video loops several times).
The only difference between the two code blocks is one uses exportAsynchronouslyWithCompletionHandler
to play the video while the other one does not.
Help? Is it possible the audio gets exported first and is ready to play before the video? Something to do with the export happening on a different thread?
func initPlayer(videoURL: NSURL) {
// Create player
player = AVPlayer(URL: videoURL)
let playerItem = player.currentItem
let asset = playerItem.asset
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = videoView.frame
view.layer.addSublayer(playerLayer)
player.seekToTime(kCMTimeZero)
player.actionAtItemEnd = .None
player.play()
// Get notified when video done for looping purposes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerItemDidReachEnd:", name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)
// Log status
println("Initialized video player: \(CMTimeGetSeconds(asset.duration)) seconds & \(asset.tracks.count) tracks for \(videoURL)")
}
func playExistingVideo() {
let filename = "/ChopsticksVideo.mp4"
let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsPath = allPaths[0] as! NSString
let exportPath = docsPath.stringByAppendingFormat(filename)
let exportURL = NSURL.fileURLWithPath(exportPath as String)!
initPlayer(exportURL)
}
Code 1:
// Create exporter
let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
exporter.videoComposition = videoComposition
exporter.outputFileType = AVFileTypeMPEG4
exporter.outputURL = exportURL
exporter.shouldOptimizeForNetworkUse = true
playExistingVideo()
Code 2:
// Create exporter
let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
exporter.videoComposition = videoComposition
exporter.outputFileType = AVFileTypeMPEG4
exporter.outputURL = exportURL
exporter.shouldOptimizeForNetworkUse = true
// -- Export video
exporter.exportAsynchronouslyWithCompletionHandler({
self.playExistingVideo()
})