Search code examples
iosswiftaudiorecording

Record audio with `m4a` container, `aac` encoding (kAudioFormatMPEG4AAC) in iOS


Failing to encode audio in aac codec.

The target record file is not found.


// Random file name with m4a extension in the documents directory. eg. "....../test.m4a"

guard let url = getFileURL(for: id) else { return }

private let recordSettings = [
                  AVFormatIDKey: kAudioFormatMPEG4AAC,
                  AVSampleRateKey: 11100,
                  AVNumberOfChannelsKey: 1,
                  AVEncoderBitRateKey: 12800,
                  AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue
   ] as [String: Any]

// Start Record
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default) // .record tries as well

try AVAudioSession.sharedInstance().setActive(true)

var soundRecorder = try AVAudioRecorder(url: url, settings: recordSettings)
soundRecorder.delegate = self
soundRecorder.prepareToRecord()
soundRecorder.record()

// ----------

// End record. Called when record stops.
soundRecorder.stop()
try setAudioSession(category: .playback)
try setAudioSession(active: false)

// That exact file name that passed during encoding

guard let url = getFileURL(for: recordId) else { return }
let audioData = try Data(contentsOf: url) // Throws an error

Error thrown,

Error Domain=NSCocoaErrorDomain Code=260 "The file “5DB71BC0-0E61-446B-ADD6-10140A58D0AC.m4a” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/890BBB09-3FEB-4B80-8873-6C2B43D1E89B/Documents/5DB71BC0-0E61-446B-ADD6-10140A58D0AC.m4a, NSUnderlyingError=0x2813ca100 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

Why is the audio data not saved there?

Further, no error thrown here,


extension AudioRecordUtil: AVAudioRecorderDelegate {
    
    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        print("audioRecorderDidFinishRecording \(flag)")
    }

    func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
        print("audioRecorderEncodeErrorDidOccur \(error ?? "")")
    }
}

Checked already for same snippet with kAudioFormatLinearPCM, kAudioFormatAppleLossless.

Both works fine with config alac (alac / 0x63616C61), 11100 Hz, mono, s32p, 276 kb/s (default). But not kAudioFormatMPEG4AAC.

I am trying to have aac for compatibility issues.

Checked similar answer as well.


Solution

  • I had to comment out these settings attributes to make it properly work with lossy kAudioFormatMPEG4AAC encoding.

    private let recordSettings = [
                      AVFormatIDKey: kAudioFormatMPEG4AAC,
    //                AVSampleRateKey: 11100,
    //                AVNumberOfChannelsKey: 1,
    //                AVEncoderBitRateKey: 12800,
                      AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue
       ] as [String: Any]