尝试将一些视频合并在一起并将它们作为单个文件导出,从查看教程/示例看,一切似乎都是正确的但是我的AVAssetExportSession似乎永远不会完整,我的视频文件永远不会被导出,任何有关明显错误的帮助我很遗憾会非常感激.
以下是合并视频的功能
注意循环中的’视频’是一个成员变量var videos = [AVAsset](),它会在调用merge之前填充(我会检查它).
private func merge() { // Create AVMutableComposition to contain all AVMutableComposition tracks var mix_composition = AVMutableComposition() var total_time_seconds = 0.0 var tracks = [AVCompositionTrack]() // Loop over videos and create tracks,keep incrementing total duration for video in videos { // Create the composition track for this video let track = mix_composition.addMutableTrackWithMediaType(AVMediaTypeVideo,preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) // Add video duration to total time total_time_seconds = total_time_seconds + video.duration.seconds // Add track to array of tracks tracks.append(track) // Add time range to track do { try track.insertTimeRange(CMTimeRangeMake(kCMTimeZero,video.duration),ofTrack: video.tracksWithMediaType(AVMediaTypeVideo)[0],atTime: video.duration) } catch _ { } } // Set total time let preferred_time_scale: Int32 = 600; let total_time = CMTimeMakeWithSeconds(total_time_seconds,preferred_time_scale) // Create main instrcution for video composition let main_instruction = AVMutableVideoCompositionInstruction() main_instruction.timeRange = CMTimeRangeMake(kCMTimeZero,total_time) // Create array to hold instructions var layer_instructions = [AVVideoCompositionLayerInstruction]() // Ensure we have the same number of tracks as videos if videos.count == tracks.count { // Loop number of videos and tracks for var index = 0; index < videos.count; ++index { // Create compositioninstruction for each track let instruction = videoCompositionInstructionForTrack(tracks[index],asset: videos[index]) if(index == 0) { instruction.setOpacity(0.0,atTime: videos[index].duration) } // Add instruction to instructions array layer_instructions.append(instruction) } } // Set tack instructions to main instruction main_instruction.layerInstructions = layer_instructions let main_composition = AVMutableVideoComposition() main_composition.instructions = [main_instruction] main_composition.frameDuration = CMTimeMake(1,30) main_composition.renderSize = CGSize(width: UIScreen.mainScreen().bounds.width,height: UIScreen.mainScreen().bounds.height) // Get path for Final video in the current project directory let documents_url = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,inDomains: .UserDomainMask)[0] let final_url = documents_url.URLByAppendingPathComponent("TEST.mp4") // Create AV Export Session let exporter = AVAssetExportSession(asset: mix_composition,presetName: AVAssetExportPresetHighestQuality) exporter!.outputURL = final_url exporter!.outputFileType = AVFileTypeMPEG4 exporter!.shouldOptimizeForNetworkUse = true exporter!.videoComposition = main_composition // Perform the Export exporter!.exportAsynchronouslyWithCompletionHandler() { dispatch_async(dispatch_get_main_queue(),{ () -> Void in self.exportDidFinish(exporter!) }) } }
下面显示了在调用exportAsynchronouslyWithCompletionHandler时调用的exportDidFinished函数.我进入这个功能,但没有发生任何事情,因为会话状态永远不会完成.
func exportDidFinish(session: AVAssetExportSession) { if session.status == AVAssetExportSessionStatus.Completed { let outputURL = session.outputURL let library = ALAssetsLibrary() if library.videoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL) { library.writeVideoAtPathToSavedPhotosAlbum(outputURL,completionBlock: { (assetURL:NSURL!,error:NSError!) -> Void in if error != nil { let alert = UIAlertView(title: "Error",message: "Video Not Saved",delegate: nil,cancelButtonTitle: "OK") alert.show() } else { let alert = UIAlertView(title: "Success",message: "Video Saved",cancelButtonTitle: "OK") alert.show() } }) } } }
打印会话状态显示它是4失败,所以我打印session.error得到了这个,但我不确定它的含义,任何帮助都会很棒
Optional(Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedDescription=Operation Stopped,NSLocalizedFailureReason=The video could not be composed.})
解决方法
如果调用了exportDidFinish但没有任何反应,则会话的状态不是AVAssetExportSessionStatus.Completed.它可能是AVAssetExportSessionStatus.Failed或其他一些值.检查这些值,如果确实失败,请检查session.error属性以获取更多信息.
编辑:如果您想要一个又一个视频播放,请只创建一个AVMutableCompositionTrack.请参阅下面的相关更改:
... var mix_composition = AVMutableComposition() // Create the composition track for the videos let track = mix_composition.addMutableTrackWithMediaType(AVMediaTypeVideo,preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) //keep track of total time var totalTime = kCMTimeZero for video in videos { // Add time range to track do { let videoTrack = video.tracksWithMediaType(AVMediaTypeVideo)[0] let videoDuration = videoTrack.duration let timeRange = CMTimeRangeMake(kCMTimeZero,videoDuration) try track.insertTimeRange(timeRange,ofTrack: videoTrack,atTime: totalTime) totalTime = CMTimeAdd(totalTime,videoDuration) } catch _ { } } // Create main instruction for video composition let main_instruction = AVMutableVideoCompositionInstruction() main_instruction.timeRange = CMTimeRangeMake(kCMTimeZero,totalTime) // Create array to hold instructions var layer_instructions = [AVVideoCompositionLayerInstruction]() // Create layer instruction let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track) // Add it to the array layer_instructions.append(layerInstruction) ...
您还需要将renderSize调整为适当的值.您的视频大小可能与屏幕大小不同.