How Meetily Handles Microphone and System Audio Capture Permissions on macOS and Windows

Meetily checks microphone permissions by attempting to open a CPAL input stream on both platforms, while system audio capture relies on macOS Screen Recording/Audio Capture permissions (14.4+) or unrestricted WASAPI loopback on Windows, with all logic implemented in the Rust Tauri core.

The open-source meeting recorder Meetily (Zackriya-Solutions/meetily) implements a cross-platform permission system in its Tauri-based Rust backend that handles microphone and system audio access differently depending on the operating system's privacy model. Understanding these permission flows is essential for developers building desktop audio applications that must comply with macOS and Windows security requirements.

Platform-Specific Permission Implementation

macOS Microphone Access

On macOS, Meetily triggers the system microphone permission dialog by attempting to open an audio input stream. The trigger_microphone_permission() function in src-tauri/src/lib.rs (lines 292-294) delegates to trigger_audio_permission() in src-tauri/src/audio/devices/discovery.rs (line 46), which tries to create a dummy CPAL input stream. If the stream opens successfully, the function returns true, indicating permission is granted. Otherwise, it logs the failure and returns false.

macOS System Audio (Screen Recording) Permissions

System audio capture on macOS requires the Screen Recording permission (renamed to Audio Capture in macOS 14.4+). The check_screen_recording_permission() function in src-tauri/src/audio/permissions.rs (lines 18-28) always returns true because macOS automatically presents the permission dialog when the CoreAudio tap is first created. If the user needs to enable this manually, request_screen_recording_permission() (lines 35-58) opens the System Settings pane directly to Privacy & Security → Screen Recording.

Windows Microphone Privacy Settings

Windows does not display custom permission dialogs within Meetily. Instead, microphone access is governed by the OS Privacy → Microphone settings. When the app calls trigger_audio_permission(), it simply attempts to start the CPAL input stream. If the user has denied access in Windows Settings, the stream creation fails and Meetily logs a permission error. No additional UI is presented by the application.

Windows System Audio (WASAPI Loopback)

System audio capture on Windows uses WASAPI loopback, which does not require explicit user consent. The check_system_audio_permissions() function in src-tauri/src/audio/capture/system.rs (lines 106-112) delegates to SystemAudioCapture::check_system_audio_permissions(), which always returns true on Windows. This allows loopback recording to work out-of-the-box without platform permission dialogs.

Permission Checking Flow

The permission verification follows a structured sequence during application startup and recording initiation:

  1. Command Registration: In src-tauri/src/lib.rs (lines 713-720), Meetily registers Tauri commands including check_screen_recording_permission_command and trigger_system_audio_permission_command via the invoke_handler.

  2. Microphone Check: When the UI invokes start_recording, the backend first runs trigger_microphone_permission(), which forwards to audio::trigger_audio_permission() and attempts to open a dummy input stream.

  3. macOS System Audio: Before capturing system audio, check_screen_recording_permission() is consulted. If permission is missing, the UI can call request_screen_recording_permission() to open System Settings.

  4. Windows System Audio: check_system_audio_permissions() immediately returns true, allowing WASAPI loopback initialization without intervention.

  5. Error Propagation: Any AudioError::PermissionDenied errors bubble up from the audio pipeline (logged in src-tauri/src/audio/pipeline.rs lines 590-601) to the frontend, where the UI displays a helpful toast notification.

Code Implementation Details

Triggering Microphone Permissions

The Rust backend attempts to trigger microphone access by creating a temporary audio stream:

// src-tauri/src/lib.rs (lines 292-294)
async fn trigger_microphone_permission() -> Result<bool, String> {
    audio::trigger_audio_permission()
        .map_err(|e| format!("Failed to trigger microphone permission: {}", e))
}

This function is invoked internally when the user initiates recording, ensuring the OS dialog appears before the actual capture begins.

Checking macOS System Audio Permissions

For macOS, the permission check acknowledges that the OS handles the dialog automatically:

// src-tauri/src/audio/permissions.rs (lines 18-28)
pub fn check_screen_recording_permission() -> bool {
    // macOS shows the dialog automatically on first capture
    info!("ℹ️  Core Audio tap requires Audio Capture permission (macOS 14.4+)");
    true
}

// Lines 35-58
pub fn request_screen_recording_permission() -> Result<()> {
    // Opens the System Settings pane so the user can enable the permission
    info!("🔐 Opening System Settings for Audio Capture permission...");
    // Platform-specific implementation opens System Settings
    Ok(())
}

Windows System Audio Permission Checks

The Windows implementation is straightforward, leveraging WASAPI's unrestricted loopback capability:

// src-tauri/src/audio/capture/system.rs (lines 106-112)
pub fn check_system_audio_permissions() -> bool {
    SystemAudioCapture::check_system_audio_permissions()
}

Frontend Integration

The TypeScript frontend triggers the permission flow before starting capture:

// UI layer (start button handler)
await invoke('start_recording', {
  mic_device_name: selectedMic,
  system_device_name: selectedSystem,
  meeting_name: 'Team Sync',
});

This invoke call triggers the Rust permission verification sequence before any audio streams are opened.

Error Handling and User Feedback

When permissions are denied, Meetily handles errors gracefully throughout the pipeline. In src-tauri/src/audio/pipeline.rs (lines 590-601), the system detects zero-audio scenarios and permission denials, logging detailed error messages while surfacing user-friendly notifications to the UI. The AudioError::PermissionDenied variant ensures specific permission-related failures are distinguished from hardware or configuration errors.

Summary

  • Microphone permissions on both platforms are verified by attempting to open a CPAL input stream, with macOS showing a system dialog and Windows relying on pre-configured Privacy settings.
  • macOS system audio requires Screen Recording/Audio Capture permission (14.4+), checked via check_screen_recording_permission() in permissions.rs, with manual settings fallback via request_screen_recording_permission().
  • Windows system audio uses WASAPI loopback and requires no explicit permission, confirmed by check_system_audio_permissions() in system.rs always returning true.
  • All permission commands are registered in lib.rs and exposed to the frontend through Tauri's invoke system, with errors handled in pipeline.rs.

Frequently Asked Questions

Does Meetily require special permissions for system audio on Windows?

No. Windows system audio capture uses WASAPI loopback, which does not require explicit user consent or permission dialogs. The check_system_audio_permissions() function returns true unconditionally, allowing immediate recording without additional OS configuration.

Why does macOS require Screen Recording permission for audio-only capture?

Starting with macOS 14.4, Apple renamed the permission to Audio Capture, but it remains grouped under the Screen Recording privacy category. This permission controls access to the CoreAudio tap API used to capture system audio output. The OS automatically prompts the user the first time the audio tap is created, though users can manually enable it in System Settings if previously denied.

How does Meetily handle microphone permission denials?

When microphone access is denied, the trigger_audio_permission() function in discovery.rs fails to open the CPAL input stream and returns an error. This error propagates through trigger_microphone_permission() in lib.rs, surfaces as an AudioError::PermissionDenied in pipeline.rs, and displays a toast notification in the UI informing the user to check their OS privacy settings.

Can users manually trigger permission requests in Meetily?

Yes, specifically for macOS system audio. While microphone permissions are triggered automatically when attempting to open the audio stream, macOS system audio provides an explicit request_screen_recording_permission() function that opens the System Settings application directly to the Screen Recording privacy pane, allowing users to manually enable the permission if it was previously denied or revoked.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →