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