AVFoundation在先前录制的视频中以特定持续时间导出带动画的视频?

时间:2013-05-06 12:08:14

标签: avfoundation cakeyframeanimation avassetexportsession avmutablecomposition avvideocomposition

我正在使用AVAssetExportSession在特定时间用我的动画导出视频。它在2天之前运行良好。现在我改变了一些东西,它停止了工作,我不知道它有什么问题。对不起代码太长了。

任何人都可以帮助我吗?

代码如下。提前谢谢。

- (IBAction)btnAddClick:(id)sender
{
//Contains CGImage of image sequence animation
gunImagesArray = [[NSMutableArray alloc]init];

//Contains CMTime array for the time duration [0-1]
keyTimesArray = [[NSMutableArray alloc]init];

for (int i = 1; i<31; i++)
{
    NSString *imageName = [NSString stringWithFormat:@"frame_%d.png",i];
    [gunImagesArray addObject:(id)[UIImage imageNamed:imageName].CGImage];
}

double currentTime = CMTimeGetSeconds(mPlayer.currentTime);
NSLog(@"currentDuration %f",currentTime);

for (int z = 1; z<31; z++)
{
    NSNumber *temp = [NSNumber numberWithFloat:(currentTime+(float)z/30)];
    [keyTimesArray addObject:temp];
}

 NSLog(@"Key Times %@",keyTimesArray);

//Create AVURLAsset from video URL
AVURLAsset* videoAsset = [AVURLAsset URLAssetWithURL:mURL options:nil];

//Create AVmutable Composition
AVMutableComposition* mixComposition = [AVMutableComposition composition];

//Create AVMutableCompositionTrack to add into AVMutableComposition
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo  preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];

//Create AVAssetTrack
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

//Calculate Video Duration Time
CMTimeRange emptyRange = CMTimeRangeMake(kCMTimeZero, CMTimeMake(videoAsset.duration.value, videoAsset.duration.timescale));
NSLog(@"Empty video track range %@", [NSValue valueWithCMTimeRange:emptyRange]);

NSError *error;
BOOL result = [mixComposition insertTimeRange:emptyRange ofAsset:videoAsset atTime:mixComposition.duration error:&error];

NSLog(@"Result = %d",result);

CGSize videoSize = [clipVideoTrack naturalSize];

NSLog(@"Video Width = %f Height = %f",videoSize.width,videoSize.height);

//ANIMATION START
CALayer *parentLayer = [CALayer layer];
parentLayer.backgroundColor = [UIColor redColor].CGColor;

CALayer *videoLayer = [CALayer layer];
videoLayer.backgroundColor = [UIColor orangeColor].CGColor;
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];

AVSynchronizedLayer *animationLayer = [CALayer layer];
animationLayer.opacity = 1.0;
animationLayer.backgroundColor = [UIColor yellowColor].CGColor;
[animationLayer setFrame:videoLayer.frame];
[parentLayer addSublayer:animationLayer];

CAKeyframeAnimation *frameAnimation = [[CAKeyframeAnimation alloc] init];
frameAnimation.beginTime = 0.1;
[frameAnimation setKeyPath:@"contents"];
frameAnimation.calculationMode = kCAAnimationDiscrete; //mode of transformation of images
[animationLayer setContents:[gunImagesArray lastObject]]; //set the array objects as encounterd
frameAnimation.autoreverses = NO; //If set Yes, transition would be in fade in fade out manner
frameAnimation.duration = 1.0; //set image duration , it can be predefined float value
frameAnimation.repeatCount = 1; //this is for inifinite, can be set to any integer value as well
[frameAnimation setValues:gunImagesArray];
[frameAnimation setKeyTimes:keyTimesArray];
[frameAnimation setRemovedOnCompletion:NO];
[frameAnimation setDelegate:self];
[animationLayer addAnimation:frameAnimation forKey:@"contents"];
//END ANIMATION

//START COMPOSING
AVMutableVideoComposition* videoComp = [AVMutableVideoComposition videoComposition];
videoComp.renderSize = videoSize;
//videoComp.renderSize = CGSizeMake(352.0, 288.0);
videoComp.renderScale = 1.0;
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:animationLayer inLayer:parentLayer];

///LAYER INSTRUCTION
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
instruction.timeRange = timeRange;

AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];

NSURL *audioURL = [[NSBundle mainBundle] URLForResource:@"Loud_Gunshot" withExtension:@"mp3"];
AVURLAsset* audioAsset1 = [[AVURLAsset alloc]initWithURL:audioURL options:nil];

NSError*nullError = NULL;
AVMutableCompositionTrack *compositionAudioTrack1 = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero,audioAsset1.duration)
                                ofTrack:[[audioAsset1 tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0]
                                 atTime:mPlayer.currentTime
                                  error:&nullError];

//Start Export Session
_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];
_assetExport.videoComposition = videoComp;

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

if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
{
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
_assetExport.outputFileType = AVFileTypeQuickTimeMovie;
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) {
     switch (_assetExport.status) {
         case AVAssetExportSessionStatusCompleted:
         {
             //YOUR FINALIZATION CODE HERE
             NSLog(@"Export Completed.");
             dispatch_async(dispatch_get_main_queue(), ^{
                 [self exportDidFinish:_assetExport];
             });
         }
             break;
         case AVAssetExportSessionStatusFailed:
         {
             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Export Failed" message:_assetExport.error.description
                                                            delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
             [alert show];
             NSLog(@"Export Failed. %@", _assetExport.error);

         }
             break;
         case AVAssetExportSessionStatusCancelled:
         {
             NSLog(@"Export Cancelled.");
         }
             break;
         default:
             break;
     }
 }];
}

-(void)exportDidFinish:(AVAssetExportSession*)session
{
NSURL *exportUrl = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:exportUrl])
{
    [library writeVideoAtPathToSavedPhotosAlbum:exportUrl completionBlock:^(NSURL *assetURL, NSError *error)
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             if (error) {
                 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed"
                                                                delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                 [alert show];
             } else {
                 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album"
                                                                delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                 [alert show];
             }
         });
     }];

}
NSLog(@"Completed");
//UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AlertView" message:@"Video is edited successfully." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
//[alert show];
}

1 个答案:

答案 0 :(得分:0)

而不是AVAssetExportPresetPassthrough使用其他预设,它可以工作。