2015-09-27 55 views
8

尝试一些影片合并到一起,并将其导出为一个单独的文件,一切似乎是正确的,从看教程/例子但是我AVAssetExportSession似乎永远不会是完整的,和我的视频文件从未出口,任何帮助,因为我失踪的一个非常明显的错误将非常感激。合并影片,但AVAssetExportSession永远不会完成

下面是我合并视频

记“视频”的循环是一个成员变量var videos = [AVAsset]()其被填充功能(它确实我检查)合并被调用之前。

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", delegate: nil, 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.}) 

回答

3

如果exportDidFinish的调用,但没有任何反应,您的会话的状态不是​​。这可能是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调整到合适的东西。您的视频的大小可能不是您屏幕的大小。

+0

实际上,我怎么检查值我打印的状态,但它只是说'“AVAssetExportSessionStatus”' – AngryDuck

+0

打印(会话!.status.rawValue)。然后打印(会话!.error) – jlw

+0

确定,所以它是状态4,它失败了,我得到这个错误“可选(错误域= AVFoundationErrorDomain代码= -11841‘停止运行’的UserInfo = {NSLocalizedDescription =停止运行,NSLocalizedFailureReason =该视频无法组成。}) ' – AngryDuck