Reputation: 3221
I'm trying to record some audio, then immediately convert it to AAC and play it back. I keep getting this error:
Recording stopped: file:///var/mobile/Containers/Data/Application/941BE30D-569E-4780-8F0D-71964E9C5561/Documents/recording.caf
Audio file duration: 3.4771882086167802 seconds
Audio buffer read successfully
AVAEInternal.h:130 [AUInterface.mm:539:SetFormat: ([[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr])] returned false, error Error Domain=NSOSStatusErrorDomain Code=-10865 "(null)"
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: '[[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr]: returned false, error Error Domain=NSOSStatusErrorDomain Code=-10865 "(null)"'
*** First throw call stack:
(0x19f280f20 0x197112018 0x19f37f66c 0x1b8df8198 0x1b8efc2a4 0x1b8efc640 0x1b8e5a744 0x1b8ed408c 0x1028e15b8 0x1028ddaa8 0x1a4947924 0x1a4061bc0 0x1a406653c 0x1a4064b20 0x1a4064a6c 0x1a4644114 0x1a384888c 0x1a32b34e8 0x1a32b5bec 0x1a32b34e8 0x1a32b07d0 0x1a32afe48 0x1a4a8ebd8 0x1a488bbb8 0x1a488a1b8 0x1a488a344 0x1a1600af4 0x1a150f560 0x1a1603b40 0x1a17ba680 0x1a17b9944 0x1a163a9e0 0x1a163c1d4 0x1a1644ecc 0x1a153784c 0x1a153576c 0x1a15353b0 0x1a1536254 0x19f253834 0x19f2537c8 0x19f251298 0x19f250484 0x19f24fcd8 0x1e41001a8 0x1a188890c 0x1a193c9d0 0x1a3440148 0x1a33ec714 0x1a33f84d0 0x1028dc500 0x1028dc5b0 0x1c2901e4c)
libc++abi: terminating due to uncaught exception of type NSException
This is the logic of the recording/conversion flow:
class AudioRecorder: ObservableObject {
@Published var isRecording = false
@Published var audioFileURL: URL?
private var audioRecorder: AVAudioRecorder?
func startRecording() {
let fileName = "recording.caf"
let filePath = getDocumentsDirectory().appendingPathComponent(fileName)
let settings = [
AVFormatIDKey: Int(kAudioFormatAppleIMA4),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
] as [String : Any]
do {
audioRecorder = try AVAudioRecorder(url: filePath, settings: settings)
audioRecorder?.record()
isRecording = true
print("Recording started: \(filePath)")
} catch {
print("Failed to start recording: \(error.localizedDescription)")
}
}
func stopRecording() {
audioRecorder?.stop()
audioRecorder = nil // Ensure the audio recorder is properly deallocated
audioFileURL = getDocumentsDirectory().appendingPathComponent("recording.caf")
isRecording = false
print("Recording stopped: \(audioFileURL?.absoluteString ?? "No file URL")")
}
func convertToAAC() {
guard let audioFileURL = audioFileURL else {
print("No audio file to convert")
return
}
do {
let file = try AVAudioFile(forReading: audioFileURL)
let duration = Double(file.length) / file.fileFormat.sampleRate
print("Audio file duration: \(duration) seconds")
if duration == 0.0 {
print("Audio file has zero duration, skipping conversion.")
return
}
if let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.length)), buffer.frameCapacity != 0 {
try file.read(into: buffer)
print("Audio buffer read successfully")
let outputFileName = "converted.m4a"
let outputFilePath = getDocumentsDirectory().appendingPathComponent(outputFileName)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
] as [String : Any]
let outputFile = try AVAudioFile(forWriting: outputFilePath, settings: settings)
let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
audioEngine.attach(playerNode)
// Use the main mixer node's output format
let mixerFormat = audioEngine.mainMixerNode.outputFormat(forBus: 0)
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: buffer.format)
audioEngine.prepare()
try audioEngine.start()
playerNode.scheduleBuffer(buffer, at: nil) {
DispatchQueue.main.async {
print("Conversion to AAC completed: \(outputFilePath)")
playerNode.stop()
audioEngine.stop()
}
}
playerNode.play()
audioEngine.mainMixerNode.installTap(onBus: 0, bufferSize: 1024, format: mixerFormat) { (buffer, time) in
do {
try outputFile.write(from: buffer)
} catch {
print("Error writing buffer to file: \(error.localizedDescription)")
}
}
} else {
print("Failed to create audio buffer or buffer frame capacity is zero")
}
} catch {
print("Error converting audio file: \(error.localizedDescription)")
}
}
private func getDocumentsDirectory() -> URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}
}
Upvotes: 2
Views: 39