2

I have 4 videos files which I have edited and added to a mutable composition. I am trying to use the export session to export the files, however, when I am exporting, only the first track in the list of tracks below gets exported

<AVAssetExportSession: 0x60800001da50, asset = <AVMutableComposition: 0x6080002240a0 tracks = (
    "<AVMutableCompositionTrack: 0x600000224ca0 trackID = 1, mediaType = vide, editCount = 8>",
    "<AVMutableCompositionTrack: 0x600000226da0 trackID = 2, mediaType = vide, editCount = 10>",
    "<AVMutableCompositionTrack: 0x60000023e180 trackID = 3, mediaType = vide, editCount = 3>",
    "<AVMutableCompositionTrack: 0x60000023e500 trackID = 4, mediaType = vide, editCount = 7>"
)>, presetName = AVAssetExportPreset1280x720, outputFileType = (null)

Only the first track with trackID = 1 gets exported. Here is the export session source:

   // Create path to output file
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                             [NSString stringWithFormat:@"ProcessedVideo-%d.mov", arc4random() % 1000]];
    NSURL *url = [NSURL fileURLWithPath:myPathDocs];

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:batchComposition presetName:AVAssetExportPreset1280x720];

    NSLog(@"%@", exporter);

    exporter.outputURL = url;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;

    [exporter exportAsynchronouslyWithCompletionHandler:^(void) {
        switch (exporter.status) {
            case AVAssetExportSessionStatusCompleted:
                NSLog(@"Completed");
                break;
            case AVAssetExportSessionStatusFailed:
                NSLog(@"Failed:%@",exporter.error);
                break;
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"Canceled:%@",exporter.error);
                break;
            default:
                break;
        }
    }];

Does anyone have any ideas how I can get all 4 tracks to export to a single .mov file using export session?

Edwin
  • 797
  • 2
  • 14
  • 23

3 Answers3

3

You can only export to one NSURL with AVAssetExportSession. If you want to export 4 separate files, you will have to export 4 times.

jlw
  • 3,166
  • 1
  • 19
  • 24
  • Ideally what I would like to do is to export those 4 tracks into one video output instead of 4 separate video files. – Edwin Oct 02 '14 at 15:35
  • 1
    You can put 4 tracks into one composition and export to one file, however whatever player you use to play it must be able to interpret a video file with more than one track of video. I believe the Photos app in iOS will only play one track and you cannot switch between tracks. – jlw Oct 02 '14 at 15:36
  • I'm using QuickTime player on the Mac. I assume that would be able top play back multiple tracks? – Edwin Oct 02 '14 at 15:48
1

Thanks to jlw for his help. What I found the problem was that I was adding multiple video tracks to mutable composition. What instead I should have done is made a single video track and applied all edits from the other asset tracks onto the single video tracks. Seems AVAssetExportSession will only export a single track as noted by jlw.

Summary:

  1. Create mutable composition
  2. Create mutable composition track
  3. Apply asset tracks to the composition (insertTimeRange)
  4. Export the mutable composition
Edwin
  • 797
  • 2
  • 14
  • 23
1

I think there is no need to create new AVMutableComposition. Instead just assign your AVVideoComposition? to the videoComposition property of your exporter.

guard let playerItem = getPlayerItem() as? AVPlayerItem else {
    return
}

let asset = playerItem.asset
let videoComposition: AVVideoComposition? = playerItem.videoComposition

let path = NSTemporaryDirectory().stringByAppendingFormat("/video.mov")
if NSFileManager.defaultManager().fileExistsAtPath(path) {
    do {
        try NSFileManager.defaultManager().removeItemAtPath(path)
    } catch {
        print("Temporary file removing error.")
    }
}
let outputURL = NSURL.fileURLWithPath(path)

guard let exporter = AVAssetExportSession(asset: asset,
                                          presetName: AVAssetExportPresetHighestQuality) else {
                                            return
}

exporter.outputURL = outputURL
exporter.outputFileType = AVFileTypeQuickTimeMovie
exporter.shouldOptimizeForNetworkUse = true
exporter.videoComposition = videoComposition // 

exporter.exportAsynchronouslyWithCompletionHandler {
    PHPhotoLibrary.sharedPhotoLibrary().performChanges({
        PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(outputURL)
    }) { (success: Bool, error: NSError?) -> Void in
        if success {
        } else {
        }
    }
}
Dmitri
  • 61
  • 1
  • 4