iOS AVFoundation Export Session is missing audio iOS AVFoundation Export Session is missing audio ios ios

iOS AVFoundation Export Session is missing audio


Here is the complete code which solved this, it has two videos whcih are combined with their audios:-

AVURLAsset* video1 = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:path1] options:nil];AVURLAsset* video2 = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:path2] options:nil];if (video1 !=nil && video2!=nil) {    // 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];    // 2 - Video track    AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];    AVMutableCompositionTrack *firstTrackAudio = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];    [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video1.duration)                        ofTrack:[[video1 tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];    [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video2.duration)                        ofTrack:[[video2 tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:video1.duration error:nil];

// it has an audio track

    if ([[video1 tracksWithMediaType:AVMediaTypeAudio] count] > 0)    {        AVAssetTrack *clipAudioTrack = [[video1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];        [firstTrackAudio insertTimeRange:CMTimeRangeMake(kCMTimeZero, video1.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];    }

// it has an audio track

    if ([[video2 tracksWithMediaType:AVMediaTypeAudio] count] > 0)    {        AVAssetTrack *clipAudioTrack = [[video2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];        [firstTrackAudio insertTimeRange:CMTimeRangeMake(kCMTimeZero, video2.duration) ofTrack:clipAudioTrack atTime:video1.duration error:nil];    }

// export session

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition                                                                      presetName:AVAssetExportPresetHighestQuality];    //Creates the path to export to  - Saving to temporary directory    NSString* filename = [NSString stringWithFormat:@"Video_%d.mov",arc4random() % 1000];    NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];    //Checks if there is already a file at the output URL.      if ([[NSFileManager defaultManager] fileExistsAtPath:path])    {        NSLog(@"Removing item at path: %@", path);        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];    }    exporter.outputURL = [NSURL fileURLWithPath:path];    //Set the output file type    exporter.outputFileType = AVFileTypeQuickTimeMovie;    path3=path;    [arr_StoredDocumentoryUrls addObject:path3];    //Exports!    [exporter exportAsynchronouslyWithCompletionHandler:^{        switch (exporter.status) {            case AVAssetExportSessionStatusCompleted:{                NSLog(@"Export Complete");                break;            }            case AVAssetExportSessionStatusFailed:                NSLog(@"Export Error: %@", [exporter.error description]);                break;            case AVAssetExportSessionStatusCancelled:                NSLog(@"Export Cancelled");                break;            default:                break;        }    }];}


Swift 4 version based on @Ashish's answer

let video1 = AVURLAsset(url: videoURL1)let video2 = AVURLAsset(url: videoURL2)// Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.let mixComposition = AVMutableComposition()guard let firstTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}guard let firstAudioTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio,preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}do {  try firstTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video1.duration),                                 of: video1.tracks(withMediaType: AVMediaType.video)[0],                                 at: kCMTimeZero)} catch {  print("error handling video1")}do {  try firstTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video2.duration),                                 of: video2.tracks(withMediaType: AVMediaType.video)[0],                                 at: kCMTimeZero)} catch {  print("error handling video2")}// if video 1 has an audio trackif video1.tracks.count > 0 {  let clipAudioTrack = video1.tracks[0]  do {    try firstAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video1.duration), of: clipAudioTrack, at: kCMTimeZero)  } catch {    print("error inserting audio track 1")  }}// if video 2 has an audio trackif video2.tracks.count > 0 {  let clipAudioTrack = video2.tracks[0]  do {    try firstAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video2.duration), of: clipAudioTrack, at: video1.duration)  } catch {    print("error inserting audio track 2")  }}// Checks if there is already a file at the output URL.if FileManager.default.fileExists(atPath: "path") {  try? FileManager.default.removeItem(atPath: "path")}// Create Exporterguard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {return}// Get pathguard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {return}let documentUrl = documentDirectory.appendingPathComponent("mergeVideo.mov")// Set the output file typeexporter.outputURL = documentUrlexporter.outputFileType = AVFileType.mov// Exports!exporter.exportAsynchronously {  switch exporter.status {  case .completed:    print("export completed")  case .failed:    print("export failed")  case .cancelled:    print("export candelled")  default:    break  }}


Try adding MobileCoreServices and execute.