2013-03-09 3 views
3

J'ai créé une méthode qui coupe et exporte des vidéos basées sur une plage de temps donnée. Il fait également tourner la vidéo au paysage.iOS AVExportSession échoue avec la vidéo découpée seulement

Pour certaines raisons cependant, AVAssetExportSession échoue lors de la tentative de traitement d'une vidéo qui a été précédemment rognée à l'aide de UIVideoEditorController.

Quelqu'un a déjà rencontré ce problème?

Je reçois cette erreur:

AVAssetExportSessionStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11841 "The operation couldn’t be completed. (AVFoundationErrorDomain error -11841.)" 

Pour cette méthode:

- (void) trimVideoWithRange: (CMTimeRange)range fromInputURL: (NSURL *)inputURL withCompletionHandler:(void (^)(BOOL success, NSURL *outputURL))handler; 
{ 
    AVAsset *asset = [AVURLAsset assetWithURL:inputURL]; 

    AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0]; 

    AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0]; 


    NSLog(@"%@, %@, %@", asset, videoTrack, audioTrack); 



    NSError *error; 

    // Create a video composition 
    AVMutableComposition *composition = [AVMutableComposition composition]; 

    AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 

    error = nil; 

    [videoCompositionTrack insertTimeRange:videoTrack.timeRange ofTrack:videoTrack atTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) error:&error]; 

    NSLog(@"videoCompositionTrack timeRange: %lld, %lld", videoCompositionTrack.timeRange.start.value, videoCompositionTrack.timeRange.duration.value); 


    if(error) 
     NSLog(@"videoCompositionTrack error: %@", error); 

    AVMutableCompositionTrack *audioCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 




    error = nil; 

    [audioCompositionTrack insertTimeRange:audioTrack.timeRange ofTrack:audioTrack atTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) error:&error]; 

    NSLog(@"audioCompositionTrack timeRange: %lld, %lld", audioCompositionTrack.timeRange.start.value, audioCompositionTrack.timeRange.duration.value); 

    if(error) 
     NSLog(@"audioCompositionTrack error: %@", error); 


    // Rotate video if needed 
    CGAffineTransform rotationTransform = videoTrack.preferredTransform; 


    // Create video composition 
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 

    videoComposition.renderScale = 1.0; 

    videoComposition.renderSize = videoTrack.naturalSize; 

    videoComposition.frameDuration = CMTimeMake(1, 30); 


    // Apply the transform which may have been changed 
    AVMutableVideoCompositionLayerInstruction *instruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; 
    [instruction setTransform:rotationTransform atTime:kCMTimeZero]; 

    // Set the time range and layer instructions for the video composition 
    AVMutableVideoCompositionInstruction *videoTrackInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 

    videoTrackInstruction.layerInstructions = [NSArray arrayWithObject:instruction]; 
    videoTrackInstruction.timeRange = range; 

    videoComposition.instructions = @[videoTrackInstruction]; 


    // Check so that we can proceed with our desired output preset 
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:composition]; 

    if (![compatiblePresets containsObject:AVAssetExportPreset960x540]) 
    { 
     // Nope. 
     if(handler) 
      handler(NO, nil); 

     return; 
    } 

    // Create export session with composition 
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPreset960x540]; 

    // Configure export session 
    exportSession.outputURL = [NSURL fileURLWithPath:pathToTemporaryOutput]; 

    exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

    exportSession.videoComposition = videoComposition; 



    exportSession.shouldOptimizeForNetworkUse = YES; 

    // Export async 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 


     switch ([exportSession status]) 
     { 
      case AVAssetExportSessionStatusCompleted: 
      { 
       dispatch_async(dispatch_get_main_queue(), ^{ 

        // Everything OK. Execute completion block with URL to rendered video 
        if(handler) 
         handler(exportSession.status == AVAssetExportSessionStatusCompleted, [NSURL fileURLWithPath:pathToTemporaryOutput]); 

       }); 



      } 
       break; 

      case AVAssetExportSessionStatusFailed: 
      { 
       NSError *exportError = exportSession.error; 

       NSLog(@"AVAssetExportSessionStatusFailed: %@", exportError.description); 

       dispatch_async(dispatch_get_main_queue(), ^{ 

        // No go. Execute handler with fail. 
        if(handler) 
         handler(NO, nil); 

       }); 
      } 
       break; 
     } 




    }]; 
} 

Répondre

1

Cela fonctionne pour moi. Ici, exportSession est AVAssetExportSession

NSURL *videoFileUrl = [NSURL fileURLWithPath:self.originalVideoPath]; 

AVAsset *anAsset = [[AVURLAsset alloc] initWithURL:videoFileUrl options:nil]; 
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:anAsset]; 
if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) { 

    self.exportSession = [[AVAssetExportSession alloc] 
          initWithAsset:anAsset presetName:AVAssetExportPresetPassthrough]; 
    // Implementation continues. 

    NSURL *furl = [NSURL fileURLWithPath:self.tmpVideoPath]; 

    self.exportSession.outputURL = furl; 
    //provide outputFileType acording to video format extension 
    self.exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

    CMTime start = CMTimeMakeWithSeconds(self.startTime, anAsset.duration.timescale); 
    CMTime duration = CMTimeMakeWithSeconds(self.stopTime-self.startTime, anAsset.duration.timescale); 
    CMTimeRange range = CMTimeRangeMake(start, duration); 
    self.exportSession.timeRange = range; 

    self.self.btnTrim.hidden = YES; 
    self.myActivityIndicator.hidden = NO; 
    [self.myActivityIndicator startAnimating]; 
    [self.exportSession exportAsynchronouslyWithCompletionHandler:^{ 

     switch ([self.exportSession status]) { 
      case AVAssetExportSessionStatusFailed: 
       NSLog(@"Export failed: %@", [[self.exportSession error] localizedDescription]); 
       break; 
      case AVAssetExportSessionStatusCancelled: 
       NSLog(@"Export canceled"); 
       break; 
      default: 
       NSLog(@"Triming Completed"); 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self.myActivityIndicator stopAnimating]; 
        self.myActivityIndicator.hidden = YES; 
       }); 

       break; 
     } 
    }]; 

} 
+0

Merci! Fonctionne très bien. – David

+3

Je suis confronté au même problème demandé ci-dessus mais, j'affecte la propriété de composition vidéo de exportsession et à cause de cela ma session d'exportation plante. Connaissez-vous la raison probable à cause de laquelle la session d'exportation pourrait tomber en panne ??? Merci à l'avance !! –

Questions connexes