I've been working on a project of video processing. Until now I succeeded in filtering live camera feeds, capturing still images, recording video from frames, recording audio, and lately succeeded in adding audio to the video capture.
But it seems like the video has lost its orientation - it should be rotated by 90 degrees clockwise. I tried to use the AVmutablevideocomposition, but whatever I do, I keep getting the following error:
[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array';
It seems like the exportUrl
is being released or something ..I tried replacing exportUrl
by outputURL
just to test it was fine..
// 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];
}
Any thoughts?