AVAssetExportSession导出失败,带有错误:“操作已停止,NSLocalizedFailureReason =video无法合成。

我们将字幕添加到用户录制的video中,但是AVAssetExportSession对象的导出未能确定性地失败:有时会起作用,有时却不起作用。 目前还不清楚如何重现错误。

我们注意到资产追踪似乎在出口时丢失了。

在导出之前,如预期的那样有两个轨道(一个用于audio,一个用于video)。 但是检查exportDidFinish中相同文件URL的轨道数量显示0个轨道。 所以出口过程似乎有些问题。

更新:注释exporter.videoComposition = mutableComposition修复错误,但当然没有变换应用于video。 所以问题似乎在于创buildAVMutableVideoComposition ,导致在导出期间出现问题。 有关AVMutableVideoComposition文档和教程很less,所以即使您没有解决scheme,但可以推荐超出Apple的参考资源,这将是有帮助的。

错误:

错误域= AVFoundationErrorDomain代码= -11841“操作停止”UserInfo = 0x170676e80 {NSLocalizedDescription =操作停止,NSLocalizedFailureReason =video不能组成。

码:

  let videoAsset = AVURLAsset(URL: fileUrl, options: nil) let mixComposition = AVMutableComposition() let videoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) let audioTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceVideoTrack, atTime: kCMTimeZero, error: nil) audioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceAudioTrack, atTime: kCMTimeZero, error: nil) // Create something mutable??? // -- Create instruction let instruction = AVMutableVideoCompositionInstruction() instruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration) let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack) instruction.layerInstructions = [videoLayerInstruction] let mutableComposition = AVMutableVideoComposition() //mutableComposition.renderSize = videoTrack.naturalSize mutableComposition.renderSize = CGSize(width: 320, height: 320) mutableComposition.frameDuration = CMTimeMake(1, 60) mutableComposition.instructions = [instruction] // Animate mutableComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer) // -- Get path let fileName = "/editedVideo-\(arc4random() % 10000).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)! println("Tracks before export: \(mixComposition.tracks.count). File URL: \(exportUrl)") // -- Remove old video? if NSFileManager.defaultManager().fileExistsAtPath(exportPath as String) { println("Deleting existing file\n") NSFileManager.defaultManager().removeItemAtPath(exportPath as String, error: nil) } // -- Create exporter let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) exporter.videoComposition = mutableComposition exporter.outputFileType = AVFileTypeMPEG4 exporter.outputURL = exportUrl exporter.shouldOptimizeForNetworkUse = true // -- Export video exporter.exportAsynchronouslyWithCompletionHandler({ self.exportDidFinish(exporter) }) func exportDidFinish(exporter: AVAssetExportSession) { println("Exported video with status: \(getExportStatus(exporter))") // Save video to photo album let assetLibrary = ALAssetsLibrary() assetLibrary.writeVideoAtPathToSavedPhotosAlbum(exporter.outputURL, completionBlock: {(url: NSURL!, error: NSError!) in println("Saved video to album \(exporter.outputURL)") if (error != nil) { println("Error saving video") } }) // Check asset tracks let asset = AVAsset.assetWithURL(exporter.outputURL) as? AVAsset println("Tracks after export: \(asset!.tracks.count). File URL: \(exporter.outputURL)") } 

问题:

1)是什么原因造成的,解决方法是什么?

2)有关如何一致地重现错误的build议,希望有助于debugging问题?

什么似乎是治愈的方法是确保assetTrack中的assetTrack参数不是来自AVURLAsset对象,而是来自addMutableTrackWithMediaType返回的video对象。

换句话说,这一行:

 let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack) 

应该:

 let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack) 

哎呀。 无休止的挫折时间,因为有时第一行工作,有时却没有。

仍然想奖赏给某人。

如果你能解释为什么第一行不是确定性的,而不是每次都失败,或者为AVMutableComposition及其相关类提供更深入的教程 – 为了给用户录制的video添加文本覆盖,赏金就是你的。 🙂

我猜你的一些video的sourceVideoTrack是:

  • 跟踪不连续
  • 时间范围比video的整个时间范围短

另一方面,可变轨道videoTrack保证了正确的时间范围(按照AVMutableVideoCompositionInstruction指示),所以它总能正常工作。

如果U设置宽度或高度为零可能导致崩溃与操作停止,NSLocalizedFailureReason =video不能构成

 self.mutableVideoComposition.renderSize = CGSizeMake(assetVideoTrack.naturalSize.height,assetVideoTrack.naturalSize.width);