2

我正在使用AVAssetExportSession在特定時間用我的動畫導出視頻。它在2天前運行良好。現在我改變了一些東西,它停止了工作,我不知道它有什麼問題。對不起,代碼太長了。AVFoundation在以前錄製的視頻中導出具有特定持續時間動畫的視頻?

任何人都可以幫助我嗎?

該代碼附在下面。提前致謝。

- (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]; 
} 
+0

你的意思是「停止工作」到底是什麼意思?你正在使用PassThrough,會添加你需要的動畫嗎? – 2013-06-20 13:11:39

+0

你是對的我不應該使用PassThrough解決了這個問題。對不起,愚蠢的問題。 – 2013-06-21 05:07:46

+0

只是好奇,表現如何?我遇到性能下降,18秒鐘可節省15秒視頻的時間... – 2013-06-21 12:36:57

回答

0

而不是AVAssetExportPresetPassthrough使用其他預設,它的工作原理。