# Meetily Platform-Specific Audio Capture APIs: WASAPI, ScreenCaptureKit, and ALSA Explained

> Discover how Meetily captures audio using WASAPI Windows, ScreenCaptureKit macOS, and ALSA Linux. Explore platform-specific APIs abstracted in Rust.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: deep-dive
- Published: 2026-07-21

---

**Meetily captures audio using WASAPI on Windows, ScreenCaptureKit with CoreAudio on macOS, and ALSA with PulseAudio on Linux, abstracting these native interfaces through a unified Rust layer.**

Meetily is an open-source meeting assistant built with Tauri and Rust that performs local transcription using OpenAI's Whisper. To achieve low-latency, high-quality audio capture across operating systems, the application implements **platform-specific audio capture APIs** through a modular architecture located in `frontend/src-tauri/src/audio/devices/`.

## Windows Audio Capture via WASAPI

On Windows, Meetily interfaces directly with the **Windows Audio Session API (WASAPI)** to enumerate and configure audio devices.

The implementation resides in [[`frontend/src-tauri/src/audio/devices/platform/windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs). The `configure_windows_audio()` function creates a WASAPI host through the `cpal` crate to enumerate all available input and output devices. For system audio capture, the implementation leverages WASAPI loopback capabilities to access the output stream without requiring external virtual cables.

When the user selects a specific device, the `get_windows_device()` function resolves the selected `AudioDevice` struct into a `cpal::Device` and selects a compatible `cpal::SupportedStreamConfig`. This returns a tuple that the audio pipeline uses to initialize the capture stream with the correct sample rate and channel configuration.

## macOS Audio Capture via ScreenCaptureKit and CoreAudio

macOS presents distinct challenges for capturing system audio versus microphone input, requiring two different APIs.

According to the source code in [[`frontend/src-tauri/src/audio/devices/platform/macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/macos.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/macos.rs), the `configure_macos_audio()` function uses **CoreAudio** for microphone enumeration while relying on **ScreenCaptureKit** for system audio capture. The implementation filters built-in speakers from standard output listings and instead routes system audio through ScreenCaptureKit's privileged capture interfaces, which require explicit user permission granted through the Tauri frontend.

This dual-API approach ensures that microphone inputs maintain low latency through CoreAudio's HAL layer, while system-wide audio capture—including application audio and browser streams—flows through Apple's modern ScreenCaptureKit framework introduced in macOS 12.3.

## Linux Audio Capture via ALSA and PulseAudio

Linux implementations must account for varying audio server configurations, from bare ALSA to PulseAudio and PipeWire environments.

The [[`frontend/src-tauri/src/audio/devices/platform/linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/linux.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/linux.rs) module implements `configure_linux_audio()` to gather microphone inputs via the default **ALSA** (Advanced Linux Sound Architecture) host. For system audio, the code specifically searches for **PulseAudio** monitor sources—virtual input devices identified by the "monitor" keyword in their name that tap into the current output stream.

This design allows Meetily to function on minimalist ALSA-only systems while fully supporting modern PulseAudio configurations without requiring root privileges. The monitor source detection occurs during device enumeration, presenting system audio as just another selectable input device in the UI.

## Cross-Platform Device Discovery Architecture

All platform-specific modules are conditionally compiled and re-exported through [[`platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/platform/mod.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/mod.rs), which uses `#[cfg(target_os = "...")]` directives to expose the correct implementation at build time.

The public API surface resides in [[`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/discovery.rs). The `list_audio_devices()` async function serves as the primary entry point, instantiating a `cpal::Host` and delegating to the appropriate platform helper (`configure_windows_audio`, `configure_macos_audio`, or `configure_linux_audio`). This abstraction ensures that higher-level components in [`pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/pipeline.rs) and [`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs) interact with a uniform `AudioDevice` struct regardless of the underlying OS-specific implementation.

```rust
// Enumerating available audio devices in a Tauri command
use crate::audio::devices::discovery::list_audio_devices;

#[tauri::command]
async fn get_available_devices() -> Result<Vec<AudioDevice>, String> {
    list_audio_devices()
        .await
        .map_err(|e| format!("Failed to list audio devices: {}", e))
}

```

## Audio Stream Configuration and Permissions

Before capturing audio, Meetily must request platform-specific permissions, particularly on macOS and Windows where sandboxing restrictions apply.

The `trigger_audio_permission()` function in [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs) builds a short-lived input stream to provoke the OS permission dialog without starting a full recording session. Once authorized, device resolution occurs through platform-specific getters like `get_windows_device()`, which return a `(cpal::Device, cpal::SupportedStreamConfig)` pair ready for the audio pipeline.

```rust
// Requesting microphone permission on macOS and Windows
use crate::audio::devices::discovery::trigger_audio_permission;

#[tauri::command]
fn request_audio_permission() -> Result<bool, String> {
    trigger_audio_permission()
        .map_err(|e| format!("Permission request failed: {}", e))
}

```

The [[`pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/pipeline.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs) module consumes these configured devices, instantiating input streams using `device.build_input_stream()`. Raw PCM data flows through Voice Activity Detection (VAD) filters, gets mixed with system audio when applicable, and forwards speech segments to the local Whisper transcription engine.

```rust
// Starting a capture stream after device configuration
let device = /* obtained from platform helper */;
let config = /* chosen SupportedStreamConfig */;

let stream = device.build_input_stream(
    &config.clone().into(),
    move |data: &[f32], _: &cpal::InputCallbackInfo| {
        // Forward raw PCM to the pipeline for mixing/VAD
        audio_pipeline.process_mic_chunk(data);
    },
    |err| eprintln!("Audio stream error: {}", err),
    None,
)?;
stream.play()?; // Begins capturing

```

## Summary

- **WASAPI** on Windows provides low-latency access to input devices and loopback capture for system audio via `configure_windows_audio()` and `get_windows_device()`.
- **ScreenCaptureKit** and **CoreAudio** on macOS handle system-wide and microphone capture respectively through `configure_macos_audio()`, filtering built-in outputs to avoid duplication.
- **ALSA** and **PulseAudio** on Linux support both direct hardware access and monitor source tapping via `configure_linux_audio()`, enabling system audio capture without additional drivers.
- The **cpal** crate abstracts these native APIs into a consistent interface, with platform-specific logic isolated in `frontend/src-tauri/src/audio/devices/platform/`.
- Device enumeration, permission handling, and stream initialization flow through [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs), while [`pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/pipeline.rs) manages the actual audio processing and transcription handoff.

## Frequently Asked Questions

### Which audio API does Meetily use on Windows?

Meetily uses the **Windows Audio Session API (WASAPI)** through the `cpal` crate. The `configure_windows_audio()` function in [`frontend/src-tauri/src/audio/devices/platform/windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs) enumerates devices using the WASAPI host and configures loopback streams for capturing system audio without virtual cables.

### How does Meetily capture system audio on macOS?

On macOS, Meetily uses **ScreenCaptureKit** for system audio and **CoreAudio** for microphone input. The implementation in [`macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/macos.rs) specifically leverages ScreenCaptureKit's privileged capture capabilities to record application and browser audio, while CoreAudio handles physical microphone devices through the HAL layer.

### Does Meetily support PulseAudio monitor sources on Linux?

Yes. The Linux implementation in [`frontend/src-tauri/src/audio/devices/platform/linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/linux.rs) automatically detects **PulseAudio** monitor sources by filtering device names for the "monitor" keyword. These virtual devices appear as selectable inputs in the UI, allowing users to record system audio alongside microphone input on PulseAudio-based systems.

### How does the application handle microphone permissions?

Meetily invokes `trigger_audio_permission()` from [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs) to request user consent on platforms requiring explicit authorization. This function creates a temporary audio stream to trigger the OS permission dialog on macOS and Windows, returning a boolean status that the Tauri frontend uses to gate recording functionality.