Last active
August 11, 2024 15:34
-
-
Save jamesgathu/82fc547e3b4988f978266dbfea28d086 to your computer and use it in GitHub Desktop.
**Merging Multiple Audio Files in iOS**
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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