---
title: "List audio devices"
url: https://recursiveai.org/oneaudio/cookbook/list-audio-devices/
description: "List the playback and recording devices in C#, find the system defaults, and open a particular device by its id, with the RecursiveAI.OneAudio.Devices…"
version: "1.2.1"
---

# List audio devices

List the playback and recording devices in C#, find the system defaults, and open a particular device by its id, with the `RecursiveAI.OneAudio.Devices` package.

```sh
dotnet add package RecursiveAI.OneAudio --version 1.2.1
dotnet add package RecursiveAI.OneAudio.Devices --version 1.2.1
```

```csharp
using OneAudio.Devices;

// The operating system's audio API: WASAPI, Core Audio or ALSA.
Console.WriteLine($"backend: {AudioDevices.Backend.Name}, " +
                  $"available: {AudioDevices.IsAvailable}");

DeviceDirection[] directions = [DeviceDirection.Output, DeviceDirection.Input];
foreach (DeviceDirection direction in directions)
{
    IReadOnlyList<AudioDeviceInfo> devices = AudioDevices.List(direction);
    AudioDeviceInfo? def = AudioDevices.Default(direction);
    Console.WriteLine($"{direction}: {devices.Count} devices, " +
                      $"default: {def?.Id ?? "none"}");
}

// Pick a device by part of its name. Id is what DeviceStreamOptions.DeviceId takes;
// it is backend specific, so match on Name and pass Id through untouched:
// new DeviceStreamOptions { DeviceId = d.Id }.
string wanted = args.Length > 0 ? args[0] : "USB Audio";
foreach (AudioDeviceInfo d in AudioDevices.List(DeviceDirection.Output))
{
    if (!d.Name.Contains(wanted, StringComparison.OrdinalIgnoreCase))
        continue;
    Console.WriteLine($"first output matching \"{wanted}\": {d.Id}");
    Console.WriteLine($"  {d.Name.Replace('\n', ' ')}");
    break;
}
```

```text
backend: alsa, available: True
Output: 90 devices, default: default
Input: 45 devices, default: default
first output matching "USB Audio": hw:CARD=Audio,DEV=0
  USB Audio, USB Audio Direct hardware device without any conversions
```

This ran on a Linux desktop with PipeWire, a USB audio interface, a webcam and HDMI outputs. ALSA lists every PCM name it knows, plug-ins included, which is why the counts are high. On Windows and macOS the list is the endpoints you see in the system’s sound settings.

- `AudioDevices.List(direction)` returns an `AudioDeviceInfo` per device: `Id`, `Name`, `IsDefault`, and, where the backend can tell, `DefaultSampleRate`, `MaxChannels` and `MinLatencyFrames`. Call it from a control thread, never from an audio callback.
- `Id` is backend specific. On ALSA it’s a PCM name such as `default` or `hw:CARD=Audio,DEV=0`; on Windows it’s the endpoint id. Don’t parse it; pass it to `DeviceStreamOptions.DeviceId`.
- With no `DeviceId`, a stream uses the system default and follows it when it changes. `SelectDevice(id)` moves an open output or input to another device; `SelectDevice(null)` goes back to the default.
- `AudioDevices.DevicesChanged` fires when devices are plugged in or removed, on WASAPI and Core Audio. ALSA has no hot-plug events, so on Linux read the list again when you need it.
- `IsAvailable` is false when the system’s audio library isn’t there, such as libasound on a server. Outputs then render silently and inputs deliver nothing.

Choosing a device and playing to it: [Play audio in C#](https://recursiveai.org/oneaudio/articles/play-audio-csharp/).
