2015-09-27 29 views
8

Cố gắng hợp nhất một số video với nhau và xuất chúng dưới dạng một tệp, mọi thứ có vẻ chính xác khi xem hướng dẫn/ví dụ, tuy nhiên AVAssetExportSession của tôi chưa bao giờ hoàn tất và tệp video của tôi không bao giờ được xuất , bất kỳ trợ giúp như một lỗi rõ ràng rõ ràng tôi đang thiếu sẽ rất đánh giá cao.Kết hợp Video nhưng AVAssetExportSession không bao giờ hoàn thành

Dưới đây là chức năng nơi tôi kết hợp các video

lưu ý 'video' trong vòng lặp là thành viên biến var videos = [AVAsset]() mà được dân cư (và nó làm tôi kiểm tra) trước khi hợp nhất được gọi.

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!) 
     }) 
    } 
} 

Dưới đây hiển thị hàm ExportDidFinished được gọi khi exportAsynchronouslyWithCompletionHandler được gọi. Tôi nhận được bên trong chức năng này nhưng không có gì xảy ra bởi vì tình trạng phiên không bao giờ được hoàn thành.

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() 
        } 
      }) 
     } 
    } 
} 

in tình trạng phiên cho thấy rằng đó là 4 được thất bại, vì vậy tôi in session.error và nhận được điều này, nhưng tôi không chắc chắn về những gì nó có nghĩa là, bất kỳ trợ giúp sẽ là tuyệt vời

Optional(Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.}) 

Trả lời

3

Nếu exportDidFinish được gọi nhưng không có gì xảy ra, trạng thái phiên của bạn không phải là AVAssetExportSessionStatus.Completed. Nó có thể là AVAssetExportSessionStatus.Failed hoặc một số giá trị khác. Kiểm tra các giá trị đó và nếu nó không kiểm tra thuộc tính session.error để biết thêm thông tin.

EDIT: Nếu bạn muốn phát một video để phát video khác, chỉ tạo một AVMutableCompositionTrack. Xem bên dưới để biết các thay đổi có liên quan:

... 
    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) 

    ... 

Bạn cũng sẽ muốn điều chỉnh renderSize thành nội dung phù hợp. Kích thước video của bạn có thể không phải là kích thước màn hình của bạn.

+0

làm thế nào để tôi thực sự kiểm tra giá trị tôi in trạng thái nhưng nó chỉ nói "" AVAssetExportSessionStatus "' – AngryDuck

+0

in (phiên! .status.rawValue). Sau đó in (session! .error) – jlw

+0

ok vì vậy nó đã được tình trạng 4 đó là không thành công, và tôi đã nhận lỗi này 'tùy chọn (lỗi tên miền = AVFoundationErrorDomain Code = -11841 "Hoạt động Ngưng" UserInfo = {NSLocalizedDescription = Hoạt động Ngưng, NSLocalizedFailureReason = Các không thể soạn video.}) ' – AngryDuck

Các vấn đề liên quan