2015-09-27 31 views
8

Bazı videoları birleştirip tek bir dosya olarak dışa aktarmayı denediğinizde, her şey öğretici/örneklere bakmaktan doğru gibi görünüyor, ancak AVAssetExportSession'ım asla tam olarak görünmüyor ve video dosyam hiçbir zaman dışa aktarılmıyor , eksik olduğum açık bir şekilde belirgin bir hataya yardımcı olmak çok takdir edilecektir. Aşağıda Birleşme Videoları ama AVAssetExportSession hiçbir zaman tamamlanmadı

i doldurulur alır üyesi değişkeni var videos = [AVAsset]() olduğu döngüde videoları

notun '' videoları birleştirmek işlevidir (ve ı kontrol yapar) birleştirme çağrılmadan önce.

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

Aşağıda exportAsynchronouslyWithCompletionHandler çağrıldığında adlandırılır exportDidFinished fonksiyonunu göstermektedir. Bu işlevin içine giriyorum ama hiçbir şey olmuyor çünkü oturum durumu hiçbir zaman tamamlanmadı.

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

oturum durumu başarısız olunmaktadır 4 olduğunu gösterdi baskılı, bu yüzden session.error basılı ve bu var, ama ne anlama geldiğini edilmeyeceğinden emin değilim, herhangi bir yardım çok iyi olurdu

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

cevap

3

exportDidFinish çağrılır, ancak hiçbir şey olmuyorsa, oturumunuzun durumu AVAssetExportSessionStatus.Completed değildir. AVAssetExportSessionStatus.Failed veya başka bir değer olabilir. Bu değerleri kontrol edin ve başarısız olursa daha fazla bilgi için session.error özelliğini kontrol edin.

EDIT: Bir videonun birbiri ardına oynatılmasını isterseniz, yalnızca bir tane AVMutableCompositionTrack oluşturun. İlgili değişiklikler için aşağıya bakın:

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

    ... 

Ayrıca renderSize'inizi uygun bir şeye ayarlamak istersiniz. Videolarınızın boyutu, ekranınızın boyutu olmayabilir.

+0

Durumu yazdırdığım değeri nasıl kontrol ederim ama sadece "AVAssetExportSessionStatus" ' – AngryDuck

+0

print (oturum! .status.rawValue). Ardından yazdır (session! .error) – jlw

+0

tamam, başarısız olan durum 4'tü ve bu hatayı aldım 'İsteğe bağlı (Hata Etki Alanı = AVFoundationErrorDomain Kodu = -11841 "İşlemi Durduruldu" UserInfo = {NSLocalizedDescription = İşlem Durduruldu, NSLocalizedFailureReason = The video oluşturulamadı.}) ' – AngryDuck

İlgili konular