Reputation: 11
I am having a difficult time determining why I am only getting the image and audio but not the video on export. Any help would be much appreciated. As you can see I have also tried using videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer
but receive an error on export. I have no preference to which method I use (videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer
or videoCompositionCoreAnimationToolWithAdditionalLayer
), I just need it work. LOL. Thank you all in advance for your help.
#import "ThirdView.h"
@implementation ThirdView
- (void)viewDidLoad {
imagePicker = [[UIImagePickerController alloc] init];
[super viewDidLoad];
}
- (NSString *) filePath: (NSString *) fileName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:fileName];
}
- (IBAction) btnClicked: (id) sender{
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
NSArray *mediaTypes =
[NSArray arrayWithObjects: (NSString *) kUTTypeMovie, nil];
imagePicker.mediaTypes = mediaTypes;
//---show the Image Picker--
[self presentModalViewController: imagePicker animated: YES] ;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
/// incoming video
NSURL *videoURL = [info valueForKey:UIImagePickerControllerMediaURL];
/// UIImage into CALayer
CALayer *aLayer = [CALayer layer];
aLayer.contents = (id) [UIImage imageNamed:@"test.png"].CGImage;
aLayer.frame = CGRectMake(0, 0, 480, 320);
/* only use with videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, 480, 320);
videoLayer.frame = CGRectMake(0, 0, 480, 320);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:aLayer];
*/
AVURLAsset* url = [AVURLAsset URLAssetWithURL:videoURL options:nil];
AVMutableComposition *videoComposition = [AVMutableComposition composition];
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
AVMutableCompositionTrack *compositionVideoTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *clipVideoTrack = [[url tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [url duration]) ofTrack:clipVideoTrack atTime:kCMTimeZero error:&error];
AVAssetTrack *clipAudioTrack = [[url tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [url duration]) ofTrack:clipAudioTrack atTime:kCMTimeZero error:&error];
AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain] ;
videoComp.renderSize = CGSizeMake(480, 320);
videoComp.frameDuration = CMTimeMake(1, 30);
//videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:aLayer inLayer:parentLayer];
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithAdditionalLayer:aLayer asTrackID:2];
/// instruction
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30) );
AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];
[layerInstruction setTrackID:2];
[layerInstruction setOpacity:1.0 atTime:kCMTimeZero ];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];
/// outputs
NSString *filePath = nil;
filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
filePath = [filePath stringByAppendingPathComponent:@"temp.mov"];
NSLog(@"exporting to: %@", filePath);
if ([fileManager fileExistsAtPath:filePath])
{
BOOL success = [fileManager removeItemAtPath:filePath error:&error];
if (!success) NSLog(@"FM error: %@", [error localizedDescription]);
}
/// exporting
AVAssetExportSession *exporter;
exporter = [[AVAssetExportSession alloc] initWithAsset:videoComposition presetName:AVAssetExportPresetHighestQuality] ;
exporter.videoComposition = videoComp;
exporter.outputURL=[NSURL fileURLWithPath:filePath];
exporter.outputFileType=AVFileTypeQuickTimeMovie;
[statusLabel setText:@"processing..."];
[exporter exportAsynchronouslyWithCompletionHandler:^(void){
switch (exporter.status) {
case AVAssetExportSessionStatusFailed:
NSLog(@"exporting failed");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(@"exporting completed");
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector (video:didFinishSavingWithError:contextInfo:), NULL);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"export cancelled");
break;
}
}];
//---hide the Image Picker---
[picker dismissModalViewControllerAnimated:YES];
[exporter autorelease];
}
- (void) video:(NSString *)videoPath
didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfo {
NSLog(@"Finished saving video with error: %@", error);
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
//---user did not select image/video; hide the Image Picker---
[picker dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[imagePicker release];
[super dealloc];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
@end
Upvotes: 1
Views: 1692
Reputation: 561
The problem with this code is that both the image and video are of same size i.e. 480x320. Hence you can either see video or image. In the commented code aLayer
is added after videoLayer
hence video is not seen and picture is. In case you solved this in different way and remember please do share the same. Thanks.
Upvotes: 0
Reputation: 1228
you have to provide the exporter the audio composition also, by setting
exporter.audioMix ;
Upvotes: 3