Meetily Platform-Specific Audio Capture APIs: WASAPI, ScreenCaptureKit, and ALSA Explained
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). 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), 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) 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/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/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 and recording_manager.rs interact with a uniform AudioDevice struct regardless of the underlying OS-specific implementation.
// 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 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.
// 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/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.
// 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()andget_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, whilepipeline.rsmanages 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 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 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →