2015-09-27 7 views
8

Versucht, einige Videos zusammenzuführen und sie als eine einzige Datei zu exportieren, scheint alles aus Tutorials/Beispiele zu sehen, aber meine AVAssetExportSession scheint nie abgeschlossen zu sein, und meine Videodatei wird nie exportiert Jede Hilfe bezüglich eines offensichtlichen Fehlers, den ich vermisse, wäre sehr willkommen.Verschmelzen von Videos, aber AVAssetExportSession beendet nie

Unten ist die Funktion, wo ich die Videos

note ‚Videos‘ in der Schleife fusionieren ist eine Membervariable var videos = [AVAsset](), die bevölkert wird (und es tut i überprüft) vor merge genannt wird.

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

Im Folgenden zeigt die exportDidFinished Funktion, die aufgerufen wird, wenn exportAsynchronouslyWithCompletionHandler genannt wird. Ich komme in diese Funktion, aber es passiert nie etwas, weil der Sitzungsstatus nie abgeschlossen ist.

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

der Sitzungsstatus gedruckt zeigte, dass es 4 war das nicht bestanden, so gedruckt i session.error und bekam, aber ich bin mir nicht sicher, was es bedeutet, jede mögliche Hilfe würde groß sein

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

Antwort

3

Wenn exportDidFinish aufgerufen wird, aber nichts passiert, ist der Status Ihrer Sitzung nicht AVAssetExportSessionStatus.Completed. Es kann AVAssetExportSessionStatus.Failed oder ein anderer Wert sein. Überprüfen Sie diese Werte und wenn es fehlgeschlagen ist, überprüfen Sie die Eigenschaft session.error auf weitere Informationen.

BEARBEITEN: Wenn ein Video nach dem anderen abgespielt werden soll, erstellen Sie nur ein AVMutableCompositionTrack. Siehe unten für relevante Änderungen:

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

    ... 

Sie sollten auch Ihre renderSize auf etwas angemessenes einstellen. Die Größe deiner Videos entspricht möglicherweise nicht der Größe deines Bildschirms.

+0

Wie überprüfe ich tatsächlich den Wert Ich druckte den Status, aber es sagte nur "AVAssetExportSessionStatus" – AngryDuck

+0

Drucken (Sitzung! .status.rawValue). Dann print (Sitzung! .Fehler) – jlw

+0

ok so war es Status 4, der fehlgeschlagen ist, und ich habe diesen Fehler 'Optional (Fehler Domain = AVFoundationErrorDomain Code = -11841 "Operation gestoppt" UserInfo = {NSLocalizedDescription = Operation beendet, NSLocalizedFailureReason = Die Video konnte nicht zusammengesetzt werden.}) ' – AngryDuck

Verwandte Themen