我们在用户录制的视频中添加了字幕,但是AVAssetExportSession对象的导出不确定性失败:有时可以,有时不能。甚至还不清楚如何重现该错误。
我们注意到资产追踪似乎在出口期间丢失了。
导出之前,有两个音轨(一个用于音频,一个用于视频)。但是,检查中的相同文件URL的轨道数exportDidFinish显示为0。因此,导出过程似乎有些问题。
exportDidFinish
更新:注释掉可以exporter.videoComposition = mutableComposition解决该错误,但是当然不对视频应用任何变换。因此,问题似乎出在create上AVMutableVideoComposition,这在导出期间导致下游问题。文档和教程AVMutableVideoComposition很少,因此,即使您没有解决方案,但可以推荐Apple以外的参考来源,这也会有所帮助。
exporter.videoComposition = mutableComposition
AVMutableVideoComposition
错误:
错误域= AVFoundationErrorDomain代码= -11841“操作已停止” UserInfo = 0x170676e80
码:
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)关于如何一致地重现错误的建议,希望可以帮助调试问题?
解决方法似乎是确保assetTrackin中的参数AVMutableVideoCompositionLayerInstruction不是来自AVURLAsset对象,而是来自所返回的视频对象addMutableTrackWithMediaType。
assetTrack
AVMutableVideoCompositionLayerInstruction
AVURLAsset
addMutableTrackWithMediaType
换句话说,这一行:
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack)
应该:
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
啊 数小时无尽的挫败感,因为有时第一行有效,有时却没有。
仍然想将赏金奖励给某人。
如果您可以解释为什么第一行会不确定地失败,而不是每次都失败,或者为AVMutableComposition及其相关类提供更深入的教程- 为了向用户录制的视频中添加文字叠加层-赏金全由您自己。:)