Search code examples
swiftmacoscore-audioavaudiosession

Record Audio on OSX (AVAudioSession not available)


I am looking to capture audio on OSX. I have IOS working with AVAudioSession, but since it is not supported on OSX, I'm having difficulty finding a simple example on OSX to record audio to a file for subsequent playback.

All the examples I find on stackoverflow have been IOS and or not in Swift.

Any help here would be appreciated. A link to a OSX Swift based simple audio capture sample code would be great.

Thanks Tom


Solution

  • AVAudioSession exists to manage iOS audio constraints. These constraints don't exist on macOS, so you don't need AVAudioSession. Hooray!

    You can capture audio to a file with AVAudioEngine and AVAudioFile:

    import Cocoa
    import AVFoundation
    
    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {
    
        @IBOutlet weak var window: NSWindow!
    
        let audioEngine = AVAudioEngine()
        var outputFile: AVAudioFile? = nil
    
        func applicationDidFinishLaunching(_ aNotification: Notification) {
            // If sandboxed, don't forget to turn on Microphone in Capabilities > App Sandbox
            let input = audioEngine.inputNode
            let bus = 0
            let inputFormat = input.inputFormat(forBus: bus)
    
            let outputURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("out.caf")
            print("writing to \(outputURL)")
    
            outputFile = try! AVAudioFile(forWriting: outputURL, settings: inputFormat.settings, commonFormat: inputFormat.commonFormat, interleaved: inputFormat.isInterleaved)
    
            input.installTap(onBus: bus, bufferSize: 512, format: inputFormat) { (buffer, time) in
                try! self.outputFile?.write(from: buffer)
            }
    
            try! audioEngine.start()
    
            DispatchQueue.main.asyncAfter(deadline: .now()+5) {
                print("Finish")
                self.audioEngine.stop()
                self.outputFile = nil
            }
        }
    }