Take the 2-minute tour ×

I'm trying to export a .mov file from a source video created by UIImagePickerController. The problem is that the output file AVAssetExportSession creates is only 668 bytes. Why is it failing? my code:

    NSURL *imagePickerVideoURL = [info objectForKey:UIImagePickerControllerMediaURL];
    NSString *filename = @"vid1.mov";

    AVAsset *video = [AVAsset assetWithURL:imagePickerVideoURL];
    AVAssetExportSession *exportSession
      = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality];
    exportSession.shouldOptimizeForNetworkUse = YES;
    exportSession.outputFileType = AVFileTypeQuickTimeMovie;
    exportSession.outputURL = [pathToSavedVideosDirectory URLByAppendingPathComponent:filename];
    NSLog(@"processing video...: %@", exportSession);
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
                       NSLog(@"done processing video!");
share|improve this question

5 Answers 5

I'm going to guess it's because exportSession was not retained in memory, thus gets killed after the didFinishPickingMediaWithInfo completes (before the export session completion handler runs).

Store exportSession to a @property or change your completion handler to copy a reference to exportSession like so:

[exportSession exportAsynchronouslyWithCompletionHandler:^{
       if (AVAssetExportSessionStatusCompleted == exportSession.status)
           NSLog(@"done processing video!");
share|improve this answer
It's a good guess but I don't think that's the problem. I use other asynchronous methods, such as network calls, and they don't auto-release themselves in mid-operation even if they aren't assigned to a (strong) property. –  yourfriendzak Aug 9 '12 at 5:43
Have you tried it anyway? I've seen this bug before and I'm 80% sure this is your problem. –  John Estropia Aug 9 '12 at 6:38
BTW, the reasoning that "other asynchronous methods don't auto-release themselves, so this one shouldn't too" is something you need to be careful of. Network calls only work that way because they are usually retained by backing NSOperations so they don't die until they complete (or fail). –  John Estropia Aug 9 '12 at 7:17
I didn't know that. I'll definitely try it out. –  yourfriendzak Aug 9 '12 at 7:34

The exportSession has an "error" property that you can check to determine what the error is. A lot of times the errors aren't particularly helpful but it's at least a place to start.

Note that I've seen issues with .mov files, where codecs in them aren't supported by AVFoundation.

share|improve this answer

Check out TSLibraryImport - the import code works.

share|improve this answer
Can it be used for UIImagePicker instead of the iPod library? –  yourfriendzak Aug 9 '12 at 3:19
TSLibrary (to extract an MPS) pulls an Asset from the library and saves it as a .MOV...image picker will not let you save it as a video as far as I know...So use the TSLibrary import code which pulls an asset and saves it as a movie, to save your movie. For flat pictures just use the saveAsJpeg function passing UIImage as a parameter. It works. –  deleted_user Aug 9 '12 at 3:26
what is MPS? And the video file I want to work with is created by uiimagepicker...its not in the library. –  yourfriendzak Aug 9 '12 at 4:53
MP3 sorry typo. Yeah but I dont think you can get the image data. I havent tried. You can get a UIImage. but I dont know that you can save a video asset from what you get from UIImagePicker. Could be wrong havent tried. But TSLibrary import shows how to get a video and store it. –  deleted_user Aug 9 '12 at 4:55

For debugging, try this...

[exportSession exportAsynchronouslyWithCompletionHandler:^
    dispatch_async(dispatch_get_main_queue(), ^{
                 NSLog(@"exportSessionMetaData:%@", exportSession.metadata);

                 if(exportSession.status == AVAssetExportSessionStatusCompleted){
                     NSError *dataReadingError = nil;
                     NSData *videoData = nil;
                     videoData = 
                                [NSData dataWithContentsOfURL:[pathToSavedVideosDirectory  

                     if (videoData != nil) {
                         // You got video data, do you work here...
                     } else {
                         NSLog(@"Failed to load the video data. ERROR:%@", dataReadingError);
share|improve this answer

you need to write down steps for video file with AVAssetExportSession..

Start with Asset Put your fileURL

AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:fileURL options:nil];

Create AVMutableComposition

AVMutableComposition* mixComposition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo  preferredTrackID:kCMPersistentTrackID_Invalid];

AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)    ofTrack:clipVideoTrack  atTime:kCMTimeZero error:nil];
[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];

    AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,videoAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];

Create AVMutableVideoComposition with Aniamtion layer if you want

AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain];
    videoComp.renderSize = CGSizeMake(videoSize.width, videoSize.height);
    videoComp.frameDuration = CMTimeMake(1, 30);
    videoComp.renderScale = 1.0;
    videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

Animation layer are here if you need otherwise pass nil.

CGSize videoSize = [videoAsset naturalSize];

//layer mixing
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];

Add aniamtion to your selected layer which you need to add as sublayer in parentLayer

Add instruction in video composition with mention animation layer and time duration.


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

Now creating AVAssetExportSession with use of AVMutableComposition and AVMutableVideoComposition

_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.videoComposition = videoComp;

//Create tmepory path for exported video file. .m4a would be preferred extension for AVFoundation.

NSString *videoName = @"demo.m4a";
NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) 
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];

Add url in Export session and some required property.

_assetExport.outputFileType = AVFileTypeQuickTimeMovie; 
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;

Start Export session and perform action when you will get complete message.

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) {
     switch (_assetExport.status)
         case AVAssetExportSessionStatusUnknown:
         case AVAssetExportSessionStatusExporting:
         case AVAssetExportSessionStatusFailed:
             NSLog(@"exporting failed");
         case AVAssetExportSessionStatusCompleted:
             NSLog(@"exporting completed");
             [self performSelectorOnMainThread:@selector(completeVideoExport) withObject:nil waitUntilDone:YES];
         case AVAssetExportSessionStatusCancelled:
             NSLog(@"export cancelled");
     _assetExport = nil;
     [_assetExport release];

if you need any more let me know..

share|improve this answer

Your Answer


