Hi I want to append voice files.
I'm recording voice with AVAudioRecorder, but to play the recording I need to call "stop", but after playing it I want to continue record. Like the native iOS Voice memo app.
Should I use AVMutableCompositionTrack and how do I do that in swift? Thanks!
If you are looking to simply pause your recording and continue it later you can use AVAudioRecorder's pause() function rather than stop() and it will continue the recording when you use play() again.
However, if you are looking to actually concatenate audio files, you can do it like this:
func concatenateFiles(audioFiles: [NSURL], completion: (concatenatedFile: NSURL?) -> ()) {
guard audioFiles.count > 0 else {
completion(concatenatedFile: nil)
return
}
if audioFiles.count == 1 {
completion(concatenatedFile: audioFiles.first)
return
}
// Concatenate audio files into one file
var nextClipStartTime = kCMTimeZero
let composition = AVMutableComposition()
let track = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
// Add each track
for recording in audioFiles {
let asset = AVURLAsset(URL: NSURL(fileURLWithPath: recording.path!), options: nil)
if let assetTrack = asset.tracksWithMediaType(AVMediaTypeAudio).first {
let timeRange = CMTimeRange(start: kCMTimeZero, duration: asset.duration)
do {
try track.insertTimeRange(timeRange, ofTrack: assetTrack, atTime: nextClipStartTime)
nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRange.duration)
} catch {
print("Error concatenating file - \(error)")
completion(concatenatedFile: nil)
return
}
}
}
// Export the new file
if let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough) {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documents = NSURL(string: paths.first!)
if let fileURL = documents?.URLByAppendingPathComponent("file_name.caf") {
// Remove existing file
do {
try NSFileManager.defaultManager().removeItemAtPath(fileURL.path!)
print("Removed \(fileURL)")
} catch {
print("Could not remove file - \(error)")
}
// Configure export session output
exportSession.outputURL = NSURL.fileURLWithPath(fileURL.path!)
exportSession.outputFileType = AVFileTypeCoreAudioFormat
// Perform the export
exportSession.exportAsynchronouslyWithCompletionHandler() { handler -> Void in
if exportSession.status == .Completed {
print("Export complete")
dispatch_async(dispatch_get_main_queue(), {
completion(file: fileURL)
})
return
} else if exportSession.status == .Failed {
print("Export failed - \(exportSession.error)")
}
completion(concatenatedFile: nil)
return
}
}
}
}