pub struct PlatformAudio { /* private fields */ }Expand description
Platform audio device management for microphone capture and speaker playout.
PlatformAudio provides access to the platform’s audio devices via WebRTC’s
Audio Device Module (ADM). Use it to:
- Enumerate available microphones and speakers
- Select which devices to use
- Create audio tracks that capture from the microphone
§Creating a PlatformAudio Instance
use livekit::PlatformAudio;
let audio = PlatformAudio::new()?;This enables the platform ADM. If an instance already exists, the new instance shares the same underlying ADM.
§Device Enumeration
// List microphones
for device in audio.recording_devices() {
println!("Mic {}: {}", device.index, device.name);
}
// List speakers
for device in audio.playout_devices() {
println!("Speaker {}: {}", device.index, device.name);
}§Device Selection
if let Some(device) = audio.recording_devices().next() {
audio.set_recording_device(&device.id)?;
}
// Hot-swap devices during active session
let devices: Vec<_> = audio.recording_devices().collect();
if let Some(device) = devices.get(1) {
audio.switch_recording_device(&device.id)?;
}§Creating Audio Tracks
use livekit::prelude::*;
let audio = PlatformAudio::new()?;
let track = LocalAudioTrack::create_audio_track("microphone", audio.rtc_source());
room.local_participant()
.publish_track(LocalTrack::Audio(track), opts)
.await?;§Lifecycle Management
PlatformAudio uses reference counting. Multiple instances share the same
underlying ADM, and the ADM is automatically disabled when all instances
are dropped.
let audio1 = PlatformAudio::new()?; // Enables ADM
let audio2 = PlatformAudio::new()?; // Shares ADM (ref_count = 2)
let audio3 = audio1.clone(); // Shares ADM (ref_count = 3)
drop(audio1); // ref_count = 2, ADM still active
drop(audio2); // ref_count = 1, ADM still active
drop(audio3); // ref_count = 0, ADM disabledYou can also explicitly release:
audio.release(); // Equivalent to drop(audio)§Platform-Specific Notes
- iOS: Creates a VPIO AudioUnit (exclusive microphone access). Drop all instances to allow other audio frameworks to use the mic.
- macOS: Uses CoreAudio for device management.
- Windows: Uses WASAPI for device management.
- Linux: Uses PulseAudio or ALSA.
Implementations§
Source§impl PlatformAudio
impl PlatformAudio
Sourcepub fn new() -> AudioResult<Self>
pub fn new() -> AudioResult<Self>
Creates a new PlatformAudio instance.
Platform ADM is always available and initialized at startup.
If another PlatformAudio instance exists, this reuses the same handle.
§Errors
Returns AudioError::PlatformInitFailed if no audio devices are available.
§Example
use livekit::PlatformAudio;
let audio = PlatformAudio::new()?;
println!("Found {} microphones", audio.recording_devices());Sourcepub fn rtc_source(&self) -> RtcAudioSource
pub fn rtc_source(&self) -> RtcAudioSource
Returns the RtcAudioSource to use when creating audio tracks.
This returns RtcAudioSource::Device, which tells the track to capture
audio from the platform’s selected recording device (microphone).
§Example
use livekit::prelude::*;
let audio = PlatformAudio::new()?;
let track = LocalAudioTrack::create_audio_track("mic", audio.rtc_source());Sourcepub fn recording_devices(
&self,
) -> impl Iterator<Item = RecordingDeviceInfo> + '_
pub fn recording_devices( &self, ) -> impl Iterator<Item = RecordingDeviceInfo> + '_
Returns an iterator over available recording (microphone) devices.
Each RecordingDeviceInfo contains the device’s unique ID, name, and index.
Use the id field with set_recording_device() for type-safe device selection.
§Platform Notes
Desktop (Windows, macOS, Linux): Full device enumeration is supported. You can enumerate USB microphones, built-in mics, audio interfaces, etc. Each device has a unique ID (GUID) and descriptive name.
Android: Only a single “default” device is reported with an empty name and ID. Android does not support app-level microphone selection - the system automatically selects the best input source based on the audio mode and connected accessories. Device enumeration on Android is not meaningful for user-facing device pickers.
iOS: Similar to desktop - devices can be enumerated, though typically only the built-in microphone and any connected accessories are available.
§Example
let audio = PlatformAudio::new()?;
for device in audio.recording_devices() {
println!("[{}] {} (ID: {})", device.index, device.name, device.id);
}
// Collect into a Vec for later use
let devices: Vec<_> = audio.recording_devices().collect();Sourcepub fn playout_devices(&self) -> impl Iterator<Item = PlayoutDeviceInfo> + '_
pub fn playout_devices(&self) -> impl Iterator<Item = PlayoutDeviceInfo> + '_
Returns an iterator over available playout (speaker) devices.
Each PlayoutDeviceInfo contains the device’s unique ID, name, and index.
Use the id field with set_playout_device() for type-safe device selection.
§Platform Notes
Desktop (Windows, macOS, Linux): Full device enumeration is supported. You can enumerate speakers, headphones, USB audio devices, HDMI outputs, etc. Each device has a unique ID (GUID) and descriptive name.
Android: Only a single “default” device is reported with an empty name and ID.
Android handles audio routing (speaker, earpiece, Bluetooth, wired headset) at the
system level via AudioManager, not through WebRTC device selection. To switch
between speaker and earpiece on Android, use the Android AudioManager API:
audioManager.setSpeakerphoneOn(true/false)audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION)
Device enumeration on Android is not meaningful for user-facing device pickers.
iOS: Similar to desktop - devices can be enumerated and selected, including built-in speaker, receiver, and connected Bluetooth/wired accessories.
§Example
let audio = PlatformAudio::new()?;
for device in audio.playout_devices() {
println!("[{}] {} (ID: {})", device.index, device.name, device.id);
}
// Collect into a Vec for later use
let devices: Vec<_> = audio.playout_devices().collect();Sourcepub fn set_recording_device(&self, id: &RecordingDeviceId) -> AudioResult<()>
pub fn set_recording_device(&self, id: &RecordingDeviceId) -> AudioResult<()>
Selects a recording (microphone) device by ID.
This is the preferred method for device selection as IDs are stable across device hot-plug events, unlike indices which can change.
§Platform Notes
Desktop: Works as expected - select from enumerated devices.
Mobile (iOS/Android): Device selection is a no-op. Both platforms handle microphone selection at the system level. This method will succeed but has no effect.
- iOS: VPIO AudioUnit handles input selection
- Android: System selects best input source based on audio mode
§Arguments
id- Device identifier fromRecordingDeviceInfo::id
§Errors
Returns AudioError::DeviceNotFound if the device ID does not exist
in the current list of available recording devices.
§Example
let audio = PlatformAudio::new()?;
// Get the first microphone (desktop only - on mobile this is a no-op)
if let Some(device) = audio.recording_devices().next() {
audio.set_recording_device(&device.id)?;
}Sourcepub fn set_playout_device(&self, id: &PlayoutDeviceId) -> AudioResult<()>
pub fn set_playout_device(&self, id: &PlayoutDeviceId) -> AudioResult<()>
Selects a playout (speaker) device by ID.
This is the preferred method for device selection as IDs are stable across device hot-plug events, unlike indices which can change.
§Platform Notes
Desktop: Works as expected - select from enumerated devices.
Mobile (iOS/Android): Device selection is a no-op. Both platforms handle audio routing at the system level. This method will succeed but has no effect.
- iOS: Use
AVAudioSessionto control routing (speaker, earpiece, Bluetooth) - Android: Use
AudioManager.setSpeakerphoneOn()to switch outputs
§Arguments
id- Device identifier fromPlayoutDeviceInfo::id
§Errors
Returns AudioError::DeviceNotFound if the device ID does not exist
in the current list of available playout devices.
§Example
let audio = PlatformAudio::new()?;
// Get the first speaker (desktop only - on mobile this is a no-op)
if let Some(device) = audio.playout_devices().next() {
audio.set_playout_device(&device.id)?;
}Sourcepub fn switch_recording_device(&self, id: &RecordingDeviceId) -> AudioResult<()>
pub fn switch_recording_device(&self, id: &RecordingDeviceId) -> AudioResult<()>
Switches the recording device while audio is active (hot-swap).
Unlike set_recording_device, this method handles the stop/change/restart
sequence required when recording is already active.
§Arguments
id- Device identifier fromRecordingDeviceInfo::id
§Errors
AudioError::DeviceNotFoundif the device is no longer availableAudioError::OperationFailedif any step fails
§Example
// During an active call, switch to a different microphone
let devices: Vec<_> = audio.recording_devices().collect();
audio.switch_recording_device(&devices[1].id)?;Sourcepub fn switch_playout_device(&self, id: &PlayoutDeviceId) -> AudioResult<()>
pub fn switch_playout_device(&self, id: &PlayoutDeviceId) -> AudioResult<()>
Switches the playout device while audio is active (hot-swap).
Unlike set_playout_device, this method handles the stop/change/restart
sequence required when playout is already active.
§Arguments
id- Device identifier fromPlayoutDeviceInfo::id
§Errors
AudioError::DeviceNotFoundif the device is no longer availableAudioError::OperationFailedif any step fails
§Example
// During an active call, switch to a different speaker
let devices: Vec<_> = audio.playout_devices().collect();
audio.switch_playout_device(&devices[1].id)?;Sourcepub fn start_recording(&self) -> AudioResult<()>
pub fn start_recording(&self) -> AudioResult<()>
Starts recording from the microphone.
Recording is automatically started when a track using RtcAudioSource::Device
is published. Use this method to resume recording after calling stop_recording.
This method turns on the system’s recording privacy indicator (e.g., the orange dot on iOS, or the microphone icon on macOS).
§Errors
Returns AudioError::OperationFailed if recording could not be started.
§Example
let audio = PlatformAudio::new()?;
audio.start_recording()?; // Resume recording after stopSourcepub fn stop_recording(&self) -> AudioResult<()>
pub fn stop_recording(&self) -> AudioResult<()>
Stops recording from the microphone.
Use this method to temporarily stop recording without disposing PlatformAudio.
This turns off the system’s recording privacy indicator (e.g., the orange
dot on iOS, or the microphone icon on macOS).
Call start_recording to resume recording.
§Note
When recording is stopped, any published audio tracks using RtcAudioSource::Device
will send silence. You should typically unpublish the track before stopping recording.
§Errors
Returns AudioError::OperationFailed if recording could not be stopped.
§Example
let audio = PlatformAudio::new()?;
// ... publish microphone track ...
// Mute: stop recording to turn off privacy indicator
room.local_participant().unpublish_track(track, false).await?;
audio.stop_recording()?;
// Unmute: start recording and republish
audio.start_recording()?;
room.local_participant().publish_track(new_track, opts).await?;Sourcepub fn is_recording_initialized(&self) -> bool
pub fn is_recording_initialized(&self) -> bool
Returns whether recording is currently initialized.
Recording is initialized when start_recording is called or when
a track using RtcAudioSource::Device is published.
Sourcepub fn release(self)
pub fn release(self)
Explicitly releases this instance’s reference to the platform ADM.
This is equivalent to drop(self). If this is the last reference,
the platform ADM is disabled and hardware resources are released.
§Example
let audio = PlatformAudio::new()?;
// ... use audio ...
audio.release(); // ADM disabled if this was the last referenceSourcepub fn is_hardware_aec_available(&self) -> bool
pub fn is_hardware_aec_available(&self) -> bool
Checks if hardware echo cancellation is available on this device.
§Platform Behavior
- iOS: Returns
true(VPIO provides hardware AEC) - Android: Returns
trueon devices with hardware AEC support - Desktop: Returns
false(hardware AEC not available)
§Example
let audio = PlatformAudio::new()?;
if audio.is_hardware_aec_available() {
println!("Hardware AEC is available");
}Sourcepub fn is_hardware_agc_available(&self) -> bool
pub fn is_hardware_agc_available(&self) -> bool
Checks if hardware automatic gain control is available on this device.
§Platform Behavior
- iOS: Returns
true(VPIO provides hardware AGC) - Android: Returns
trueon devices with hardware AGC support - Desktop: Returns
false(hardware AGC not available)
Sourcepub fn is_hardware_ns_available(&self) -> bool
pub fn is_hardware_ns_available(&self) -> bool
Checks if hardware noise suppression is available on this device.
§Platform Behavior
- iOS: Returns
true(VPIO provides hardware NS) - Android: Returns
trueon devices with hardware NS support - Desktop: Returns
false(hardware NS not available)
Sourcepub fn active_aec_type(&self) -> AudioProcessingType
pub fn active_aec_type(&self) -> AudioProcessingType
Gets the type of echo cancellation currently active.
§Returns
AudioProcessingType::Hardwareif hardware AEC is available and enabledAudioProcessingType::Softwareif using WebRTC’s software AECAudioProcessingType::Noneif AEC is disabled
§Example
let audio = PlatformAudio::new()?;
match audio.active_aec_type() {
AudioProcessingType::Hardware => println!("Using hardware AEC"),
AudioProcessingType::Software => println!("Using software AEC"),
AudioProcessingType::None => println!("AEC disabled"),
}Sourcepub fn active_agc_type(&self) -> AudioProcessingType
pub fn active_agc_type(&self) -> AudioProcessingType
Gets the type of automatic gain control currently active.
Sourcepub fn active_ns_type(&self) -> AudioProcessingType
pub fn active_ns_type(&self) -> AudioProcessingType
Gets the type of noise suppression currently active.
Sourcepub fn configure_audio_processing(
&self,
options: AudioProcessingOptions,
) -> AudioResult<()>
pub fn configure_audio_processing( &self, options: AudioProcessingOptions, ) -> AudioResult<()>
Configures audio processing with the given options.
This method configures echo cancellation, noise suppression, and automatic gain control based on the provided options.
§Platform Behavior
- iOS:
prefer_hardware_processingis ignored (always uses VPIO) - Android: When
prefer_hardware_processingisfalse, hardware effects are disabled and WebRTC’s software APM is used instead - Desktop:
prefer_hardware_processingis ignored (hardware not available)
§Example
use livekit::{PlatformAudio, AudioProcessingOptions};
let audio = PlatformAudio::new()?;
// Use defaults (software processing recommended)
audio.configure_audio_processing(AudioProcessingOptions::default())?;
// Disable echo cancellation
audio.configure_audio_processing(AudioProcessingOptions {
echo_cancellation: false,
..Default::default()
})?;Sourcepub fn set_echo_cancellation(
&self,
enable: bool,
prefer_hardware: bool,
) -> AudioResult<()>
pub fn set_echo_cancellation( &self, enable: bool, prefer_hardware: bool, ) -> AudioResult<()>
Enables or disables echo cancellation.
This is a convenience method equivalent to calling configure_audio_processing
with only the echo_cancellation field changed.
§Arguments
enable-trueto enable AEC,falseto disableprefer_hardware-trueto prefer hardware AEC on supported devices
Sourcepub fn set_auto_gain_control(
&self,
enable: bool,
prefer_hardware: bool,
) -> AudioResult<()>
pub fn set_auto_gain_control( &self, enable: bool, prefer_hardware: bool, ) -> AudioResult<()>
Enables or disables automatic gain control.
§Arguments
enable-trueto enable AGC,falseto disableprefer_hardware-trueto prefer hardware AGC on supported devices
Sourcepub fn set_noise_suppression(
&self,
enable: bool,
prefer_hardware: bool,
) -> AudioResult<()>
pub fn set_noise_suppression( &self, enable: bool, prefer_hardware: bool, ) -> AudioResult<()>
Enables or disables noise suppression.
§Arguments
enable-trueto enable NS,falseto disableprefer_hardware-trueto prefer hardware NS on supported devices
Trait Implementations§
Source§impl Clone for PlatformAudio
impl Clone for PlatformAudio
Source§fn clone(&self) -> PlatformAudio
fn clone(&self) -> PlatformAudio
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more