Skip to content

Instantly share code, notes, and snippets.

@jamesgathu
Last active August 11, 2024 15:34
Show Gist options
  • Save jamesgathu/82fc547e3b4988f978266dbfea28d086 to your computer and use it in GitHub Desktop.
Save jamesgathu/82fc547e3b4988f978266dbfea28d086 to your computer and use it in GitHub Desktop.
**Merging Multiple Audio Files in iOS**
/**
provide an array of audio files urls and get them merged
Its important to note that the process is asynchronous and that one would need to show user some sort of a progress indicator
so that the process does not get interupted
- parameter audioFileUrls: an array of audio file urls
- returns String representing the newly merged file or nil for a failure
*/
func mergeAudioFiles(audioFileUrls: [URL]) -> String? {
let composition = AVMutableComposition()
for i in 0 ..< audioFileUrls.count {
let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
let filePath = "\(Utilities.getDocumentsDirectory())"+Utilities.getFileName(audioFileUrls[i].path)
let asset = AVURLAsset(url: URL(string: filePath)!)
let trackContainer = asset.tracks(withMediaType: AVMediaType.audio)
guard trackContainer.count > 0 else{
return nil
}
let audioTrack = trackContainer[0]
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: audioTrack.timeRange.duration)
try! compositionAudioTrack.insertTimeRange(timeRange, of: audioTrack, at: composition.duration)
}
let finalUrl = URL(string: "\(getDocumentsDirectory())\(UUID().uuidString)_audio.m4a")
let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
assetExport?.outputFileType = AVFileType.m4a
assetExport?.outputURL = finalUrl
assetExport?.exportAsynchronously(completionHandler:{
self.hud.dismiss()
switch assetExport!.status
{
case AVAssetExportSessionStatus.failed:
print("AUDIO_MERGE -> failed \(String(describing: assetExport!.error!))")
case AVAssetExportSessionStatus.cancelled:
print("AUDIO_MERGE -> cancelled \(String(describing: assetExport!.error))")
case AVAssetExportSessionStatus.unknown:
print("AUDIO_MERGE -> unknown\(String(describing: assetExport!.error))")
case AVAssetExportSessionStatus.waiting:
print("AUDIO_MERGE -> waiting\(String(describing: assetExport!.error))")
case AVAssetExportSessionStatus.exporting:
print("AUDIO_MERGE -> exporting\(String(describing: assetExport!.error) )")
default:
print("Audio Concatenation Complete")
print("Old audio :: \(getFileName(audioFileUrls[0]!.path))")
print("New audio :: \(getFileName(finalUrl!.path))")
print("Merged :: \(getFileName(finalUrl!.path))")
}
})
return finalUrl!.path
}
/**
Get the set document directory for the application
*/
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
/**
get filename from a given file url or path
- parameter fileUrl: file path to be extracted
- returns: filename : String
*/
func getFileName(_ fileUrl : String) -> String{
return URL(string: fileUrl)!.lastPathComponent
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment