Microphone and Audio Configuration

The Stream Video SDK provides comprehensive audio configuration capabilities, allowing you to control microphone input, audio output devices, and manage audio routing during video calls. The SDK abstracts the complexities of audio device management while providing platform-specific optimizations.

Before attempting to access the user’s audio devices, ensure the appropriate permissions are set in both the iOS plist file and Android Manifest. You can read more about permissions in installation section.

Basic Audio Operations

Microphone Control

Enable or disable the microphone during a call:

// Enable microphone
await call.setMicrophoneEnabled(enabled: true);

// Disable microphone (mute)
await call.setMicrophoneEnabled(enabled: false);

Audio Input Device Management

Select and configure specific microphone devices:

// Set a specific audio input device
await call.setAudioInputDevice(device);

// Get current microphone device
var currentInput = call.state.value.audioInputDevice;

Audio Output Device Management

Control where audio is played back:

// Set a specific audio output device
await call.setAudioOutputDevice(device);

// Get current audio output device
var currentOutput = call.state.value.audioOutputDevice;

Platform-Specific Audio Routing

iOS Audio Route Selection

On iOS, the preferred way to handle external audio device selection is through the native audio route picker, as iOS doesn’t allow apps to implicitly set external device output:

// Trigger the native iOS audio route selection UI
await RtcMediaDeviceNotifier.instance.triggeriOSAudioRouteSelectionUI();

On iOS, use triggeriOSAudioRouteSelectionUI() instead of setAudioOutputDevice() for external audio devices like AirPods, Bluetooth headphones, or external speakers. This provides the native iOS experience users expect and respects iOS audio routing policies.

Device Discovery and Management

Listing Connected Devices

Query all connected audio devices:

// Get all audio input devices (microphones)
final audioInputDevices = RtcMediaDeviceNotifier.instance.audioInputs();

// Get all audio output devices (speakers/headphones)
final audioOutputDevices = RtcMediaDeviceNotifier.instance.audioOutputs();

Enumerating Devices

For more comprehensive device querying, use the enumerateDevices method:

// Get all available devices
final allDevicesResult = await RtcMediaDeviceNotifier.instance.enumerateDevices();

allDevicesResult.fold(
  success: (success) {
    // Process all devices
    for (final device in success.data) {
      print('Device: ${device.label}, Kind: ${device.kind}');
    }
  },
  failure: (failure) {
    print('Failed to enumerate devices: ${failure.error.message}');
  },
);

// Get devices filtered by kind
final audioInputResult = await RtcMediaDeviceNotifier.instance.enumerateDevices(
  kind: RtcMediaDeviceKind.audioInput,
);

final audioOutputResult = await RtcMediaDeviceNotifier.instance.enumerateDevices(
  kind: RtcMediaDeviceKind.audioOutput,
);

Listening to Device Changes

Monitor when audio devices are connected or disconnected:

// Listen for device changes
RtcMediaDeviceNotifier.instance.onDeviceChange.listen((devices) {
  // Filter for audio input devices
  final audioInputDevices = devices.where(
    (device) => device.kind == RtcMediaDeviceKind.audioInput
  );
  
  // Filter for audio output devices
  final audioOutputDevices = devices.where(
    (device) => device.kind == RtcMediaDeviceKind.audioOutput
  );
  
  // Automatically switch to the first available microphone
  if (audioInputDevices.isNotEmpty) {
    call.setAudioInputDevice(audioInputDevices.first);
  }
});

Error Handling

Implement proper error handling for audio operations:

final result = await call.setMicrophoneEnabled(enabled: true);

result.fold(
  success: (success) {
    print('Microphone enabled successfully');
  },
  failure: (failure) {
    print('Failed to enable microphone: ${failure.error.message}');
  },
);
© Getstream.io, Inc. All Rights Reserved.