2013-03-09 73 views
3

我創建了一個修剪和導出基於給定時間範圍的視頻的方法。它也將視頻旋轉到風景。iOS AVExportSession失敗,僅修剪視頻

由於某些原因,AVAssetExportSession在嘗試處理之前使用UIVideoEditorController修剪的視頻時失敗。

之前有人遇到過這個問題嗎?

我得到這個錯誤:

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

對於這種方法:

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




    }]; 
} 

回答

1

這對我的作品。這裏exportSessionAVAssetExportSession

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

謝謝!很棒。 – David 2013-05-19 11:03:00

+3

我面臨着上述問題,但是,我正在分配exportsession的視頻組合屬性,因爲我的導出會話崩潰。你知道可能的原因,因爲哪個輸出會話可能會崩潰嗎?感謝提前! – 2013-12-06 06:23:59