title: Merging audio with AVAssetExportSession
body: <p>I'd like to merge two audio files without too much overhead time. The following code successfully merges the audio but takes way too long (&gt;30seconds for more than a couple minutes of audio), and I'm wondering if there is any way to expedite that process. I read in a couple places to use <code>AVAssetExportPresetPassthrough</code>, but I can't seem to get that preset to work with any file type. The only settings I've been able to get to work are using <code>AVAssetExportPresetAppleM4A</code> and exporting as a <code>.m4a</code></p>
  <p>Code to create AVAssetExportSession</p>
  <pre><code>if (audioHasBeenRecorded) {
    // Merge recordings
    let composition = AVMutableComposition()
    let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
  
    guard let start = recorder.timeStart else { return }
    
    compositionAudioTrack?.insert(originalRecording: FileManagerHelper.recordingLocalURL(secondRecording: false), insertedRecording: FileManagerHelper.recordingLocalURL(secondRecording: true), startTime: CMTime(seconds: start, preferredTimescale: 1000000))
  
    if let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) {
      print(assetExport.supportedFileTypes)
      assetExport.outputFileType = AVFileType.m4a
      assetExport.outputURL = FileManagerHelper.recordingLocalURL(secondRecording: false)
      do { // Delete old audio
          try FileManager.default.removeItem(at: FileManagerHelper.recordingLocalURL(secondRecording: false))
          try FileManager.default.removeItem(at: FileManagerHelper.recordingLocalURL(secondRecording: true))
      } catch { log(error.localizedDescription, msgType: .error) }
     
      assetExport.exportAsynchronously(completionHandler: {
        if let error = assetExport.error {
          log(error, msgType: .error)
        } else {
          log(&quot;Successfully merged recordings!&quot;, msgType: .error)
          self.idea.numberOfPoints = self.audioVisualizer.count
          self.idea.save()
          
          self.setupPlayer() // Prepare to play the recorded audio file
          self.seekTo(TimeInterval((recorder.timeStart ?? 0) + (recorder.timeEnd ?? 0)))
          DispatchQueue.main.async { [ weak self ] in
            guard let self = self else { return }
            self.audioVisualizer.visualize(self.idea)
          }
        }
      })
    }
  }
  </code></pre>
  <p>Insert code:</p>
  <pre><code>extension AVMutableCompositionTrack {
    func insert(originalRecording: URL, insertedRecording: URL, startTime: CMTime) {
      let originalAsset = AVURLAsset(url: originalRecording)
      let insertedAsset = AVURLAsset(url: insertedRecording)
  
      let range1 = CMTimeRangeMake(start: CMTime.zero, duration: startTime)
      let range2 = CMTimeRangeMake(start: CMTime.zero, duration: insertedAsset.duration)
      let range3 = CMTimeRangeMake(start: startTime + insertedAsset.duration, duration: originalAsset.duration - startTime)
      if let originalTrack = originalAsset.tracks(withMediaType: AVMediaType.audio).first,
         let insertedTrack = insertedAsset.tracks(withMediaType: AVMediaType.audio).first {
           try? insertTimeRange(range1, of: originalTrack, at: CMTime.zero)
           try? insertTimeRange(range2, of: insertedTrack, at: startTime)
           try? insertTimeRange(range3, of: originalTrack, at: startTime + insertedAsset.duration)
      }
    }
  }
  </code></pre>