Skip to main content
The AudioManager class provides centralized control over audio session configuration, device management, and audio processing for LiveKit.

Singleton Access

let audioManager = AudioManager.shared

Audio Device Management (macOS)

outputDevices
[AudioDevice]
List of available output devices (macOS only).
inputDevices
[AudioDevice]
List of available input devices (macOS only).
outputDevice
AudioDevice
Currently selected output device.On macOS, you can set this to change the output device.
inputDevice
AudioDevice
Currently selected input device.On macOS, you can set this to change the input device.
defaultOutputDevice
AudioDevice
The default output device for the system.
defaultInputDevice
AudioDevice
The default input device for the system.

Audio Session Configuration (iOS/tvOS/visionOS)

isSpeakerOutputPreferred
Bool
default:"true"
Determines whether the device’s built-in speaker or receiver is preferred for audio output.
  • true: Speaker is preferred
  • false: Receiver is preferred
Only applies when audio output is routed to the built-in speaker or receiver. Ignored if customConfigureAudioSessionFunc is set.
sessionConfiguration
AudioSessionConfiguration?
Specifies a fixed configuration for the audio session, overriding dynamic adjustments.When set, takes precedence over dynamic configuration logic including isSpeakerOutputPreferred.
Ignored if customConfigureAudioSessionFunc is set.

Voice Processing

isVoiceProcessingEnabled
Bool
default:"true"
The main flag that determines whether to enable Voice-Processing I/O of the internal AVAudioEngine.
Toggling this requires restarting the AudioEngine. It is recommended to keep this true and toggle isVoiceProcessingBypassed when possible.
Setting this to false prevents voice-processing initialization and muted talker detection will not work.
isVoiceProcessingBypassed
Bool
default:"false"
Bypass Voice-Processing I/O of internal AVAudioEngine.Can be toggled at runtime without restarting the AudioEngine.
isVoiceProcessingAGCEnabled
Bool
Enable or bypass the Auto Gain Control of internal AVAudioEngine.Can be toggled at runtime.

Audio Processing

capturePostProcessingDelegate
AudioCustomProcessingDelegate?
Delegate to modify the local audio buffer before it is sent to the network.
Only one delegate can be set at a time. If you only need to observe (not modify) the buffer, use add(localAudioRenderer:) instead.
renderPreProcessingDelegate
AudioCustomProcessingDelegate?
Delegate to modify the combined remote audio buffer (all tracks) before it is played to the user.
Only one delegate can be set at a time. If you only need to observe the buffer, use add(remoteAudioRenderer:) instead.

Ducking Control

isAdvancedDuckingEnabled
Bool
default:"false"
Enables “advanced ducking” of other audio while using Apple’s voice processing APIs.When enabled, the system dynamically adjusts ducking based on voice activity:
  • More ducking when someone is speaking
  • Less ducking when neither side is speaking (SharePlay/FaceTime-like behavior)
Defaults to false, which keeps a fixed ducking behavior with minimal ducking to keep other audio as loud as possible.
duckingLevel
AudioDuckingLevel
default:".min"
Controls how much other audio is reduced (“ducked”) while using Apple’s voice processing APIs.Available on iOS 17+, macOS 14.0+, visionOS 1.0+.
  • .min: Keep other audio as loud as possible (SDK default)
  • .default: Apple’s historical fixed ducking amount
  • .max: Better voice intelligibility, more ducking

Recording

isRecordingAlwaysPreparedMode
Bool
Whether recording is kept initialized for low-latency publish.
isMicrophoneMuted
Bool
The mute state of the internal audio engine using Voice Processing I/O mute API.Normally handled automatically, but can be set manually if needed.
isManualRenderingMode
Bool
Whether manual rendering (no-device) mode is enabled.
isEngineRunning
Bool
Whether the internal AVAudioEngine is currently running.
engineAvailability
AudioEngineAvailability
The current availability state of the audio engine.

Callbacks

onDeviceUpdate
OnDevicesDidUpdate?
Callback invoked when audio devices change.
AudioManager.shared.onDeviceUpdate = { audioManager in
    print("Audio devices updated")
}
onMutedSpeechActivity
OnSpeechActivity?
Detect voice activity even if the mic is muted.
Internal audio engine must be initialized by calling prepareRecording() or connecting to a room.
AudioManager.shared.onMutedSpeechActivity = { audioManager, event in
    print("Speech activity: \(event)")
}

Methods

setVoiceProcessingEnabled(_:)

Set whether voice processing is enabled.
try AudioManager.shared.setVoiceProcessingEnabled(true)
Throws: Error if the setting cannot be applied.

setManualRenderingMode(_:)

Enable manual rendering mode where you provide audio buffers.
try AudioManager.shared.setManualRenderingMode(true)
In this mode:
  • Provide audio buffers via AudioManager.shared.mixer.capture(appAudio:)
  • Remote audio will not play automatically
  • Get remote audio with add(remoteAudioRenderer:) or per-track renderers

setRecordingAlwaysPreparedMode(_:)

Prepare the microphone capture pipeline for low-latency publishing.
try await AudioManager.shared.setRecordingAlwaysPreparedMode(true)
When enabled:
  • Audio engine starts configured for mic input in muted state
  • Keeps recording initialized and pre-warms voice processing
  • Persists across Room lifecycles until disabled
Note: Microphone permission is required. iOS may prompt if not granted.

startLocalRecording()

Start mic input to the SDK even without a Room or connection.
try AudioManager.shared.startLocalRecording()
Audio buffers will flow into LocalAudioTrack renderers and capturePostProcessingDelegate.

stopLocalRecording()

Stop mic input started with startLocalRecording().
try AudioManager.shared.stopLocalRecording()

setEngineAvailability(_:)

Set whether the internal AVAudioEngine is allowed to run.
try AudioManager.shared.setEngineAvailability(.enabled)
This flag has highest priority over any API that may start the engine. Useful for CallKit flows where you need to set up connections without touching the audio device yet.

add(localAudioRenderer:)

Add a renderer to receive PCM buffers from local input (mic).
AudioManager.shared.add(localAudioRenderer: myRenderer)

add(remoteAudioRenderer:)

Add a renderer to receive PCM buffers from combined remote audio.
AudioManager.shared.add(remoteAudioRenderer: myRenderer)
For individual track buffers, use RemoteAudioTrack.add(audioRenderer:) instead.

set(engineObservers:)

Set a chain of AudioEngineObservers.
AudioManager.shared.set(engineObservers: [observer1, observer2])
Defaults to having a single AudioSessionEngineObserver initially.

Example Usage

// Configure audio session for speaker output
AudioManager.shared.isSpeakerOutputPreferred = true

// Enable low-latency recording
try await AudioManager.shared.setRecordingAlwaysPreparedMode(true)

// Monitor speech activity while muted
AudioManager.shared.onMutedSpeechActivity = { _, event in
    print("Speech detected: \(event.isSpeaking)")
}

// Add local audio renderer
AudioManager.shared.add(localAudioRenderer: myAudioProcessor)

// On macOS, change audio device
#if os(macOS)
if let device = AudioManager.shared.inputDevices.first(where: { $0.name == "My Mic" }) {
    AudioManager.shared.inputDevice = device
}
#endif

Build docs developers (and LLMs) love