swiftcocoaavaudiorecorder

What is correct usage of AVAudioRecorder in Cocoa (macOS)?


I have a simple app where I try to do audio recordings on macOS using Swift and Cocoa. I get an audio file produced but with nothing in it. The whole app is basically in an NSWindowController. It has this relevant code.

// member variable for recorder
var recorder : AVAudioRecorder?

// function called indirectly from UI to begin recording
func startRecording() throws {
    let settings = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
    ]
    
    let rec = try AVAudioRecorder(url: filename, settings: settings)
    rec.delegate = self
    rec.prepareToRecord()

    rec.isMeteringEnabled = true
    rec.record()
    self.recorder = rec
}

// Callback I use to stop recording
@IBAction func stop(sender: AnyObject) {
    self.recorder?.stop()
    self.recorder = nil
}

For Signing & Capabilities I have the following checked. I am not sure if my code is wrong or if there is something wrong with my capabilities.

enter image description here

The strange thing is that I get this style of code working in Playgrounds. This code will work in playgrounds, but it doesn't look fundamentally different from my GUI app code:

import Speech

let paths = FileManager.default.urls(
    for: .documentDirectory, 
    in: .userDomainMask)
let docsDir = paths[0]
let filename = docsDir.appendingPathComponent("voiceRec.m4a")


let settings = [
    AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
    AVSampleRateKey: 12000,
    AVNumberOfChannelsKey: 1,
    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]

let rec = try AVAudioRecorder(
    url: filename, 
    settings: settings)
var ok = rec.prepareToRecord()

ok = rec.record()

// Evaluate this in playground when you are done recording
rec.stop()

Solution

  • You need to add the NSMicrophoneUsageDescription key to your Info.plist file. This is required to allow access to the microphone. Remember both iOS and macOS run in sandbox and will not allow the app to do anything it has not been given explicit permission to do. The NSMicrophoneUsageDescription has to have a description of what the microphone will be used for so that a user of the application can read the reason given and judge if it is valid, or whether that particular feature is something they want to use.

    enter image description here

    You just paste the key in as shown. You need to add another entry by clicking the plus (+) button on a row above.

    Also make sure that microphone input is enabled under capabilities:

    enter image description here

    You can see an example of how the Info.plist should look

    <key>NSMicrophoneUsageDescription</key>
    <string>Record audio to file to later transcribe</string>
    <key>NSPrincipalClass</key>
    <string>NSApplication</string>
    <key>NSSpeechRecognitionUsageDescription</key>
    <string>For transcribing recorded audio</string>
    

    Thanks to @jnpdx for clarifying this point in a comment.