1

我一直在處理視頻處理項目。到目前爲止,我成功地過濾了實時相機Feed,捕獲靜止圖像,從幀錄製視頻,錄製音頻,並且最近成功地爲視頻捕獲添加了音頻。不可改變的構圖,在將幀添加到用視頻製作的視頻時丟失方向

但它看起來像視頻已經失去了方向 - 它應該順時針旋轉90度。我試圖用AVmutablevideocomposition,但無論我做什麼,我不斷收到以下錯誤:

[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array';

好像被釋放的exportUrl什麼的..我試圖取代exportUrl通過outputURL只是爲了測試它是罰款..

// adding audio to video 
AVMutableComposition *composition = [[AVMutableComposition alloc]init]; 
AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:recordedTmpFile options:nil]; 
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:outputURL options:nil]; 
// 

AVMutableCompositionTrack *compositionCommentaryTrack = 
    [composition addMutableTrackWithMediaType:AVMediaTypeAudio 
       preferredTrackID:kCMPersistentTrackID_Invalid]; 
[compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) 
    ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
    atTime:kCMTimeZero error:nil]; 

AVMutableCompositionTrack *compositionVideoTrack = 
    [composition addMutableTrackWithMediaType:AVMediaTypeVideo 
       preferredTrackID:kCMPersistentTrackID_Invalid]; 
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
    ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
    atTime:kCMTimeZero error:nil]; 

AVAssetExportSession* _assetExport = 
    [[AVAssetExportSession alloc] initWithAsset:composition 
            presetName:AVAssetExportPresetPassthrough]; 

NSString* videoName = @"export.mov"; 
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName]; 
self.exportUrl = [[NSURL fileURLWithPath:exportPath]retain]; 

if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) { 
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil]; 
} 

_assetExport.outputFileType = AVFileTypeQuickTimeMovie; 
_assetExport.outputURL = self.exportUrl; 
_assetExport.shouldOptimizeForNetworkUse = YES; 
[_assetExport exportAsynchronouslyWithCompletionHandler: 
    ^(void) { 
     switch (_assetExport.status) 
     { 
     case AVAssetExportSessionStatusCompleted: 
      //    export complete 
      NSLog(@"Export Complete"); 
      break; 
     case AVAssetExportSessionStatusFailed: 
      NSLog(@"Export Failed"); 
      NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]); 
      //    export error (see exportSession.error) 
      break; 
     case AVAssetExportSessionStatusCancelled: 
      NSLog(@"Export Failed"); 
      NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]); 
      //    export cancelled 
      break; 
     } 
    }]; ; 
// 

// trying to rotate the video 
// if I replace exportUrl by outputURL no error 

AVURLAsset* asset = [[AVURLAsset alloc]initWithURL:self.exportUrl options:nil]; 
AVMutableVideoComposition* videoComposition = [[AVMutableVideoComposition videoComposition]retain]; 
videoComposition.renderSize = CGSizeMake(320, 240); 
videoComposition.frameDuration = CMTimeMake(1, 30); 
AVMutableVideoCompositionInstruction *instruction = 
    [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)); 
AVMutableVideoCompositionLayerInstruction* rotator = 
    [AVMutableVideoCompositionLayerInstruction 
     videoCompositionLayerInstructionWithAssetTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]]; 

CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation(0,-320);  
CGAffineTransform rotateBy90Degrees = CGAffineTransformMakeRotation(M_PI/2); 
CGAffineTransform shrinkWidth = CGAffineTransformMakeScale(0.66, 1); 
CGAffineTransform finalTransform = CGAffineTransformConcat(shrinkWidth, CGAffineTransformConcat(translateToCenter, rotateBy90Degrees)); 
[rotator setTransform:finalTransform atTime:kCMTimeZero]; 
instruction.layerInstructions = [NSArray arrayWithObject: rotator]; 
videoComposition.instructions = [NSArray arrayWithObject: instruction]; 

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:self.exportUrl]) { 
    [library writeVideoAtPathToSavedPhotosAlbum:self.exportUrl completionBlock:nil]; 
    [outputURL release]; 
} 

有什麼想法?

回答

3

我想出了這個問題。

下面的代碼現在:

  AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:recordedTmpFile options:nil]; 
     AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:outputURL options:nil]; 

     AVMutableComposition* composition = [AVMutableComposition composition]; 
     // 
     AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
     videoComposition.frameDuration = CMTimeMake(1,30); 
     videoComposition.renderScale = 1.0; 
     // 

     AVMutableCompositionTrack *compositionCommentaryTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio 
     preferredTrackID:kCMPersistentTrackID_Invalid]; 
     [compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) 
     ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
     atTime:kCMTimeZero error:nil]; 

     AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo 
     preferredTrackID:kCMPersistentTrackID_Invalid]; 
     [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
     ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
     atTime:kCMTimeZero error:nil]; 

     // 
     AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 

     AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack]; 

     AVAssetTrack *sourceVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 


     CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(M_PI/2); 
     CGAffineTransform rotateTranslate = CGAffineTransformTranslate(rotationTransform,320,0); 

     [compositionVideoTrack setPreferredTransform:sourceVideoTrack.preferredTransform]; 
     [layerInstruction setTransform:rotateTranslate atTime:kCMTimeZero]; 

     instruction.layerInstructions = [NSArray arrayWithObject: layerInstruction]; 
     videoComposition.instructions = [NSArray arrayWithObject: instruction]; 

     // 


     AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:composition 
     presetName:AVAssetExportPresetPassthrough]; 

     NSString* videoName = @"export.mov"; 

     NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName]; 
     self.exportUrl = [NSURL fileURLWithPath:exportPath]; //url of your video created from image 

     if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) 
     { 
     [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil]; 
     } 

     _assetExport.outputFileType = @"com.apple.quicktime-movie"; 
     NSLog(@"file type %@",_assetExport.outputFileType); 
     _assetExport.outputURL = self.exportUrl; 
     _assetExport.shouldOptimizeForNetworkUse = YES; 

     [_assetExport exportAsynchronouslyWithCompletionHandler: 
     ^(void) { 
      switch (_assetExport.status) 
      { 
       case AVAssetExportSessionStatusCompleted: 
        //    export complete 
        NSLog(@"Export Complete"); 
        break; 
       case AVAssetExportSessionStatusFailed: 
        NSLog(@"Export Failed"); 
        NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]); 
        //    export error (see exportSession.error) 
        break; 
       case AVAssetExportSessionStatusCancelled: 
        NSLog(@"Export Failed"); 
        NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]); 
        //    export cancelled 
        break; 
      } 
     }]; 



     ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
     if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:self.exportUrl]) { 
      [library writeVideoAtPathToSavedPhotosAlbum:self.exportUrl completionBlock:nil]; 
      [outputURL release]; 
     } 
+1

您的代碼不旋轉真正的視頻幀。對於旋轉,您需要將AVMutableVideoComposition對象分配給您的AVAssetExportSession,如下所示:'_assetExport.videoComposition = videoComposition' – 2013-09-19 11:56:00

+2

目前,您只是設置了prefferedTransform,它告訴玩家在播放之前旋轉視頻。它無處不在,如果你上傳到youtube或facebook,旋轉將會丟失。 – 2013-09-19 12:05:18