在使用帧制作的视频中添加音频时,可以使用合成,丢失方向

时间:2012-07-10 13:26:54

标签: ios avfoundation avassetwriter avassetexportsession avmutablecomposition

我一直致力于视频处理项目。到目前为止,我成功地过滤了实时摄像头,捕获静止图像,从帧录制视频,录制音频,最近成功地为视频捕获添加了音频。

但似乎视频已失去方向 - 它应顺时针旋转90度。我试图使用AVmutablevideocomposition,但无论我做什么,我都会收到以下错误:

  

[__ NSArrayM objectAtIndex:]:索引0超出空数组的界限';

似乎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];
} 

有什么想法吗?

1 个答案:

答案 0 :(得分: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];
        }