How Meetily Handles Audio Permissions and Device Access Across Platforms

Meetily implements a platform-aware Rust abstraction layer that explicitly checks macOS screen-recording permissions while delegating microphone grants to OS-level prompts on Windows and Linux, exposing these controls via Tauri commands for seamless frontend integration.

Meetily, an open-source meeting assistant built by Zackriya-Solutions, manages cross-platform audio capture through a centralized Rust backend that abstracts permission complexity away from the UI. The implementation in src-tauri/src/audio/ provides unified device discovery while respecting platform-specific privacy requirements for microphone and system audio access.

Platform-Specific Permission Workflows

Meetily’s permission strategy varies by operating system, with macOS requiring explicit user consent for system audio capture while Windows and Linux rely on automatic or policy-based grants.

macOS Screen Recording and Microphone Requirements

On macOS, Meetily must request two distinct permissions:

  • Microphone access – Handled via standard AVCaptureDevice APIs when the app first attempts to open an input device
  • Screen recording permission – Required specifically for system audio capture through ScreenCaptureKit, implemented in src-tauri/src/audio/permissions.rs

The core permission functions reside in permissions.rs:

// Checking and requesting screen-recording permission (macOS only)
pub fn ensure_screen_recording_permission() -> bool {
    if !check_screen_recording_permission() {
        if let Err(e) = request_screen_recording_permission() {
            log::error!("Failed to request screen-recording permission: {}", e);
            return false;
        }
    }
    true
}

The trigger_system_audio_permission() function specifically handles the ScreenCaptureKit authorization flow. If the user denies access, the error propagates to audio::core-old.rs where it is logged as “Permission denied for audio device …”, allowing the UI to surface appropriate guidance.

Windows and Linux OS-Level Grants

Windows and Linux implementations require no explicit permission code in the Meetily codebase:

  • Windows – Microphone access is granted automatically by the OS when the Tauri app requests it, with the system prompt appearing on first use. System audio capture utilizes WASAPI loop-back, which does not require additional user grants.
  • Linux – Microphone access is governed by PulseAudio or ALSA policies. The trigger_system_audio_permission() function logs “System audio permissions not required on this platform” and returns immediately, as the underlying audio subsystem handles authorization.

Device Discovery Architecture

All audio device enumeration flows through a centralized discovery layer that delegates to platform-specific implementations.

Platform Abstraction in discovery.rs

The src-tauri/src/audio/devices/discovery.rs module serves as the entry point for enumerating input and output devices. It delegates to specialized modules located in src-tauri/src/audio/devices/platform/:

Microphone and System Audio Capture

Device-specific access is split between two primary modules:

Microphone input – src-tauri/src/audio/devices/microphone.rs exposes default_input_device() and list_input_devices(). The selected device name travels from the frontend through invoke('start_recording', { mic_device_name, … }) to the Rust command handler in audio::recording_commands.rs.

System audio – src-tauri/src/audio/devices/speakers.rs manages output device enumeration, while src-tauri/src/audio/capture/system.rs handles the actual capture. On macOS, this delegates to capture/core_audio.rs using ScreenCaptureKit; on Windows and Linux, it utilizes platform-specific loop-back mechanisms that require no explicit permissions.

All device structs are wrapped in Arc<RwLock<…>> and shared through audio::recording_state.rs, enabling thread-safe concurrent access from the audio pipeline, VAD (Voice Activity Detection), and Whisper transcription workers.

Frontend Integration via Tauri Commands

The permission helpers are registered as async Tauri commands in src-tauri/src/lib.rs (lines 713‑720) and exposed to the TypeScript frontend:

// Frontend permission check flow
import { invoke } from '@tauri-apps/api/tauri';

async function enableSystemAudio() {
  const hasPerm = await invoke<boolean>('check_screen_recording_permission_command');
  if (!hasPerm) {
    await invoke('request_screen_recording_permission_command');
  }
  // After permission, start system-audio capture
  await invoke('start_system_audio_capture', { device_name: 'BlackHole 2ch' });
}

The onboarding flow in src-tauri/src/onboarding.rs (step 4 for macOS) invokes these commands to guide users through required grants before recording begins.

Error Handling and Permission Propagation

When the OS denies microphone access, the error surfaces in audio::pipeline.rs (lines 590‑601) with the message “Permission denied for audio device …”. The frontend can detect these failures through the Result returned by the start_recording command:

#[tauri::command]
async fn start_recording(
    mic_device_name: Option<String>,
    system_device_name: Option<String>,
    meeting_name: Option<String>,
) -> Result<(), String> {
    audio::recording_commands::start_recording(mic_device_name, system_device_name, meeting_name).await
}

This architecture ensures that permission handling remains centralized in the Rust layer, keeping the frontend code agnostic of platform-specific APIs while maintaining strict privacy controls.

Summary

  • macOS requires explicit handling – Meetily checks screen-recording permission via src-tauri/src/audio/permissions.rs before capturing system audio, while microphone access follows standard AVCaptureDevice flows.
  • Windows and Linux use OS-level grants – No explicit permission code exists for these platforms; microphone access is automatic (Windows) or policy-based (Linux), and system audio capture requires no additional user consent.
  • Unified device discovery – The discovery.rs module abstracts platform-specific implementations in audio/devices/platform/, returning consistent device lists across macOS, Windows, and Linux.
  • Thread-safe state management – All device handles are wrapped in Arc<RwLock<…>> and managed through recording_state.rs for safe concurrent access.
  • Tauri command bridge – Frontend TypeScript calls Rust commands registered in lib.rs to check and request permissions, with onboarding logic in onboarding.rs guiding macOS users through the grant flow.

Frequently Asked Questions

Why does Meetily require screen recording permission on macOS for audio capture?

macOS routes system audio capture through ScreenCaptureKit, which Apple classifies under the screen-recording permission category. When you invoke check_screen_recording_permission_command or request_screen_recording_permission_command from the frontend, the backend calls AVCaptureDevice::requestAccess APIs in src-tauri/src/audio/permissions.rs. This permission is separate from microphone access and specifically enables capturing application audio output without looping physical cables.

How does Meetily handle missing microphone permissions?

If the OS denies microphone access, the Rust backend logs “Permission denied for audio device …” in src-tauri/src/audio/core-old.rs and returns an error through the start_recording command’s Result<(), String> type. The frontend can catch this error and prompt the user to check system privacy settings, as the Tauri commands do not automatically retry denied microphone requests on Windows or Linux.

Can users select specific audio devices rather than using defaults?

Yes. The audio::devices::microphone.rs module provides list_input_devices() to enumerate available sources. Users pass a specific mic_device_name or system_device_name parameter to the start_recording Tauri command. The backend validates this device name against the discovery cache in recording_state.rs before initializing the capture stream, falling back to the default device only if no name is specified.

Is there a difference in privacy implications between platforms?

Yes. On macOS, Meetily must explicitly request screen-recording permission for system audio, which the user can revoke at any time in System Settings. Windows grants microphone access automatically on first use through WASAPI, though users can later disable it in Privacy settings. Linux relies on PulseAudio/ALSA policies, meaning permissions are typically managed at the system level rather than per-application, resulting in no runtime prompts during the onboarding flow defined in src-tauri/src/onboarding.rs.

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 →