之前我曾尝试过这样做,但没有得到任何答复。所以我会再试一次。我正试图在视频(如涂鸦或边框)上放置图像。我调用“addAnimation”方法三次,然后运行,但只在第一次尝试时调用exportAsynchronouslyWithCompletionHandler。有任何想法吗?
- (void)addAnimation:(UIImage *)background for:(NSString *)socialSite
{
// 1 - Load Asset
AVURLAsset* videoAsset = [AVURLAsset URLAssetWithURL:self.videoUrl options:nil];
// 2 - Create AVMutableComposition Object
AVMutableComposition* mixComposition = [AVMutableComposition composition];
// 2.1 - VideoTrack
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
// 2.2 - AudioTrack
AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
//If either of them are nil, then alloc
if( (self.clipVideoTrack == nil) || (self.clipAudioTrack == nil)){
self.clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
self.clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
}
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:self.clipVideoTrack atTime:kCMTimeZero error:nil];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:self.clipAudioTrack atTime:kCMTimeZero error:nil];
CGSize videoSize = [self.clipVideoTrack naturalSize];
// 3 - Background layer
UIImage *myImage = background;
CALayer *aLayer = [CALayer layer];
if(socialSite == nil) {
aLayer.contents = (id)myImage.CGImage;
if(__IPHONE_4_INCH)
aLayer.frame = CGRectMake(0, 0, 640, 640);
else
aLayer.frame = CGRectMake(0, 0, 320, 320);
}
else{
aLayer.contents = (id)myImage.CGImage;
aLayer.frame = CGRectMake(0, 0, myImage.size.width, myImage.size.height);
}
// 3.1 - Video layer
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, myImage.size.width, myImage.size.height);
if(socialSite == nil){
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
}
else{
videoLayer.frame = CGRectMake(0, 110, videoSize.width, videoSize.height);
}
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:aLayer];
// 3.2 - Add instructions
AVMutableVideoComposition* videoComp = [AVMutableVideoComposition videoComposition];
videoComp.renderSize = videoSize;
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);
AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];
AVAssetExportSession *assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];//AVAssetExportPresetPassthrough
assetExport.videoComposition = videoComp;
// 4 - Get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
myPathDocs = [myPathDocs stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// 5 - Create exporter
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = videoComp;
[exporter exportAsynchronouslyWithCompletionHandler:^ {
NSData *video;
/*********************************** INSTAGRAM *********************************************/
if([socialSite isEqualToString:@"instagram"]){
video = [NSData dataWithContentsOfURL:exporter.outputURL];
[MPOCreateMPManager sharedManager].createdMarcoPolo.instagramVideo = video;
NSLog(@"IG SIZE (In CreateViewController): %lu",(unsigned long)[MPOCreateMPManager sharedManager].createdMarcoPolo.instagramVideo.length);
}
/*********************************** FB/TWITTER *********************************************/
else if ([socialSite isEqualToString:@"facebook"]){
video = [NSData dataWithContentsOfURL:exporter.outputURL];
[MPOCreateMPManager sharedManager].createdMarcoPolo.fBTwitterVideo = video;
NSLog(@"FB SIZE (In CreateViewController): %lu",(unsigned long)[MPOCreateMPManager sharedManager].createdMarcoPolo.fBTwitterVideo.length);
}
/*********************************** DOODLE *********************************************/
else if (socialSite == nil){
video = [NSData dataWithContentsOfURL:exporter.outputURL];
[MPOCreateMPManager sharedManager].createdMarcoPolo.video = video;
[MPOCreateMPManager sharedManager].createdMarcoPolo.image = [self loadImage:exporter.outputURL];
NSLog(@"*******************************DOODLE DONE*************************************");
}
}];
}